猿问

Linq to Entity with Repository Pattern 和 EF

我最近一直在研究实体框架和存储库模式,在存储库类中,我创建了一个名为 find 的函数,它使用谓词从中生成实体。这是我的存储库功能。


public T Find(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderby = null, string includeProperties = "")

{

    IQueryable<T> query = dbSet;

    if (filter != null)

    {

        query = query.Where(filter);

    }

    foreach(var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))

    {

        query = query.Include(includeProperty);

    }


    if (orderby != null)

    {

        return orderby(query).First();

    }

    else

    {

        return query.First();

    }

}

这是我的 DTO 课程。


public class UsersDo

{

    public int UserId {get;set}

    public string Username {get;set}

    ...

}

现在我在我的页面上调用 Find 函数,例如:


usersDao.Find(x=>x.Username == "username")

但是我得到了错误


The entity or complex type 'UsersDo' cannot be constructed in a LINQ to Entities query.

谁能建议这里出了什么问题。


在存储库类下编辑

,我有一个构造函数:


private readonly DbSet<T> dbSet;

private readonly DataContext context;

public GenericDao(DataContext _context)

{

    context = _context;

    dbSet = context.Set<T>();

}

我的道课:


public class UsersDao : GenericDao<UsersDo>, IUsers

{

     public UsersDao(DataContext context) : base (context) {}

     ...

}



梦里花落0921
浏览 86回答 3
3回答

大话西游666

问题是 userDoa 未在您的 DbContext 中注册实体。还,public class UsersDao : GenericDao<UsersDo>, IUsers{&nbsp; &nbsp; &nbsp;public UsersDao(DataContext context) : base (context) {}&nbsp; &nbsp; &nbsp;...}我相信不需要。该问题与您的通用存储库无关。public class DataContext : DbContext{&nbsp; &nbsp; &nbsp;public virtual DbSet<UserDo> UserDos { get; set; }}public class UserDo&nbsp;{&nbsp; &nbsp; [Key]&nbsp; &nbsp; public int UserId {get;set}&nbsp; &nbsp; public string Username {get;set}}然后var result = new UserContext().Find(x => x.Username == "John");

茅侃侃

你能试试这个public class UserContext : DbContext{&nbsp; &nbsp; public DbSet<UsersDo> Users { get; set; }&nbsp; &nbsp; protected override void OnModelCreating(DbModelBuilder modelBuilder)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Entity<UsersDo>()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasKey(e => e.UsersId);&nbsp; &nbsp; &nbsp; &nbsp; base.OnModelCreating(modelBuilder);&nbsp; &nbsp; }}public class Repo<T> where T : class{&nbsp; &nbsp; private readonly DbSet<T> dbSet;&nbsp; &nbsp; public Repo(DbContext context)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; dbSet = context.Set<T>();&nbsp; &nbsp; }&nbsp; &nbsp; public T Find(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderby = null, string includeProperties = "")&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; IQueryable<T> query = dbSet;&nbsp; &nbsp; &nbsp; &nbsp; if (filter != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; query = query.Where(filter);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; query = query.Include(includeProperty);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (orderby != null)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; query = orderby(query);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // If you use the First() method you will get an exception when the result is empty.&nbsp; &nbsp; &nbsp; &nbsp; return query?.FirstOrDefault();&nbsp; &nbsp; }}-------- 测试代码internal class Program{&nbsp; &nbsp; private static void Main(string[] args)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var usersDao = new Repo<UsersDo>(new UserContext());&nbsp; &nbsp; &nbsp; &nbsp; var r = usersDao.Find(x => x.Username == "username");&nbsp; &nbsp; }}

catspeake

我强烈推荐一种简化的存储库模式,这将有助于模拟您的数据源以进行测试,并提供更大的灵活性。我不建议使用通用存储库,而是将存储库类似于控制器。(我为一组特定的操作提供数据)这减少了依赖引用的数量,尽管有利于 SRP 而不是 DNRY。例如:public class OrderRepository : IOrderRepository{&nbsp; &nbsp; private MyDbContext Context&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return _contextLocator.Get<MyDbContext>() ?? throw new InvalidOperation("The repository must be called from within a context scope.");&nbsp; &nbsp; }&nbsp; &nbsp; IQueryable<Order> IOrderRepository.GetOrders()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var query = Context.Orders.Where(x => x.IsActive);&nbsp; &nbsp; &nbsp; &nbsp; return query;&nbsp; &nbsp; }&nbsp; &nbsp; IQueryable<Order> IOrderRepository.GetOrderById(int orderId)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var query = Context.Orders.Where(x => x.IsActive && x.OrderId == orderId);&nbsp; &nbsp; &nbsp; &nbsp; return query;&nbsp; &nbsp; }&nbsp; &nbsp; Order IOrderRepository.CreateOrder( /* Required references/values */)&nbsp; &nbsp; {&nbsp; &nbsp; }&nbsp; &nbsp; void IOrderRepository.DeleteOrder(Order order)&nbsp; &nbsp; {&nbsp; &nbsp; }}通过返回 IQueryable,消费代码可以保持对可选过滤条件、排序、分页和对数据的操作的控制,而不会触发不必要的数据读取。不需要用于过滤、排序的复杂表达式参数或用于管理分页的额外参数。存储库充当 IsActive、授权检查等所需过滤器的看门人。存储库还可以充当实体工厂,确保在创建新实体时提供所有必填字段和引用。我还让存储库管理删除操作,以确保强制执行所有验证和完整性,以及审计记录,并处理软删除场景。(活跃)有些人回避使用 IQueryable,因为它会将 EF 主义“泄漏”到控制器中。然而,它泄露它们只不过是传递表达式以试图抽象出 EF 的复杂方法。每个条件表达式都同样容易需要符合 EF-isms。(即传递引用实体上的私有方法或静态方法的 order-by 表达式)像这样的存储库模式(相对于只让代码访问 DbSet)的好处是易于测试。模拟存储库只需要返回 aList<T> AsQueryable并且您的控制器等可以单独测试。它还为所需的过滤器和针对实体的操作提供了很好的集中化。
随时随地看视频慕课网APP
我要回答