IDbSet 上没有FindAsync()方法
有没有理由从IDbSet
接口中省略FindAsync()
方法? Find
是界面的一部分,异步版本不可用似乎很奇怪。 我需要DbSet
转换为DbSet
来访问它,这有点麻烦:
User user = await ((DbSet)db.Users) .FindAsync("de7d5d4a-9d0f-48ff-9478-d240cd5eb035");
如果您拥有IDbSet
的使用者,我认为您这样做是因为您希望从使用者中访问FindAsync()
,那么一个简单的解决方案是创建您自己的包含IDbSet的接口并包含任何FindAsync()
您要使用的方法:
public interface IAsyncDbSet : IDbSet where T : class { Task FindAsync(params Object[] keyValues); }
这解决了不必转换为DbSet的问题 – 顺便说一下,它破坏了合同编码的抽象性好处。 但这也引入了一系列问题。
需要更多工作的更好的解决方案(imo)是定义一个接口,该接口仅包含您要在DbSet对象中使用的成员,在实现接口时子类DbSet,然后在代码中使用该接口:
public interface IMyAsyncDbSet where TEntity : class { TEntity Add(TEntity entity); TEntity Remove(TEntity entity); // Copy other methods from IDbSet as needed. Task
这是一个适配器模式,真的。 它将您的代码所期望的接口与Entity Framework提供的接口分离。 现在,它们是相同的 – 这就是为什么除了inheritanceDbSet
之外什么都不做。 但后来他们可能会分歧。 此时,您仍然可以使用最新的DbSet而不会破坏您的代码。
以下是我在其中一个项目中解决这个问题的方法:
using System.Threading.Tasks; namespace System.Data.Entity { public static class IDbSetExtensions { /// /// If possible asynchronously finds an entity with the given primary key values /// otherwise finds the entity synchronously. /// If an entity with the given primary key values exists in the context, then it is /// returned immediately without making a request to the store. Otherwise, a /// request is made to the store for an entity with the given primary key values /// and this entity, if found, is attached to the context and returned. If no /// entity is found in the context or the store, then null is returned. /// /// /// /// The values of the primary key for the entity to be found. /// A task that represents the asynchronous find operation. The task result contains /// the entity found, or null. /// public static async Task FindAsync (this IDbSet @this, params object[] keyValues) where TEntity : class { DbSet thisDbSet = @this as DbSet ; if (thisDbSet != null) { return await thisDbSet.FindAsync(keyValues); } else { return @this.Find(keyValues); } } } }
有人可能会考虑将Find方法包装在异步同步模式中,该模式将提供卸载(并且不像真正的异步方法那样具有可伸缩性)。 但是,调用者必须知道这一点,以确保在调用可能会干扰的FindAsync方法后,他们不会在上下文中调用方法。 让调用者意识到特定的实现并不是一个非常好的设计,但是因为它很容易导致问题。 对于OP,IDbSet是DbSet,但是调用将是异步的。
我相信这些天(因为EF 6)的正确方法涉及从DbSetinheritance而不是实现IDbSet。
将FindAsync方法更改为FirstOrDefaultAsync(x => x.Id == yourId);
使用此扩展来解决FindAsync问题
/// /// IDbSet extension /// public static class IDbSetExtension { public static Task FindAsync (this IDbSet set, params object[] keyValues) where TEntity : class { return Task .Run(() => { var entity = set.Find(keyValues); return entity; }); } }
- 更改ASP.NET标识存储用户数据的数据库
- 如何在ASP.Net MVC 5视图中获取ApplicationUser的自定义属性值?
- 如何在ASP .NET MVC 5中为AspNetUser创建SecurityStamp
- 如何设置asp.net标识cookie到期时间
- Asp.net Identity 2.0使用自定义的唯一属性扩展UserValidator
- 使用自定义角色在ASP.NET标识中初始化RoleManager
- 使ASP.NET Identity 2.0电子邮件确认令牌适用于WCF和MVC
- Identity Owin是否需要LazyLoading?
- 如何在ASP.NET IDENTITY中添加自定义表?