亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Linq to Entity with Repository Pattern 和 EF

Linq to Entity with Repository Pattern 和 EF

C#
夢里花落0921 2022-07-10 15:58:29
我最近一直在研究實體框架和存儲庫模式,在存儲庫類中,我創建了一個名為 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) {}     ...}
查看完整描述

3 回答

?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

問題是 userDoa 未在您的 DbContext 中注冊實體。


還,


public class UsersDao : GenericDao<UsersDo>, IUsers

{

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

     ...

}

我相信不需要。該問題與您的通用存儲庫無關。


public class DataContext : DbContext

{

     public virtual DbSet<UserDo> UserDos { get; set; }

}


public class UserDo 

{

    [Key]

    public int UserId {get;set}


    public string Username {get;set}

}

然后


var result = new UserContext().Find(x => x.Username == "John");


查看完整回答
反對 回復 2022-07-10
?
茅侃侃

TA貢獻1842條經驗 獲得超21個贊

你能試試這個


public class UserContext : DbContext

{

    public DbSet<UsersDo> Users { get; set; }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)

    {

        modelBuilder.Entity<UsersDo>()

            .HasKey(e => e.UsersId);


        base.OnModelCreating(modelBuilder);

    }

}


public class Repo<T> where T : class

{

    private readonly DbSet<T> dbSet;


    public Repo(DbContext context)

    {

        dbSet = context.Set<T>();

    }


    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)

        {

            query = orderby(query);

        }


        // If you use the First() method you will get an exception when the result is empty.

        return query?.FirstOrDefault();

    }

}

-------- 測試代碼


internal class Program

{

    private static void Main(string[] args)

    {

        var usersDao = new Repo<UsersDo>(new UserContext());


        var r = usersDao.Find(x => x.Username == "username");

    }

}


查看完整回答
反對 回復 2022-07-10
?
catspeake

TA貢獻1111條經驗 獲得超0個贊

我強烈推薦一種簡化的存儲庫模式,這將有助于模擬您的數據源以進行測試,并提供更大的靈活性。我不建議使用通用存儲庫,而是將存儲庫類似于控制器。(我為一組特定的操作提供數據)這減少了依賴引用的數量,盡管有利于 SRP 而不是 DNRY。


例如:


public class OrderRepository : IOrderRepository

{

    private MyDbContext Context

    {

        return _contextLocator.Get<MyDbContext>() ?? throw new InvalidOperation("The repository must be called from within a context scope.");

    }


    IQueryable<Order> IOrderRepository.GetOrders()

    {

        var query = Context.Orders.Where(x => x.IsActive);

        return query;

    }


    IQueryable<Order> IOrderRepository.GetOrderById(int orderId)

    {

        var query = Context.Orders.Where(x => x.IsActive && x.OrderId == orderId);

        return query;

    }


    Order IOrderRepository.CreateOrder( /* Required references/values */)

    {

    }


    void IOrderRepository.DeleteOrder(Order order)

    {

    }

}

通過返回 IQueryable,消費代碼可以保持對可選過濾條件、排序、分頁和對數據的操作的控制,而不會觸發不必要的數據讀取。不需要用于過濾、排序的復雜表達式參數或用于管理分頁的額外參數。存儲庫充當 IsActive、授權檢查等所需過濾器的看門人。存儲庫還可以充當實體工廠,確保在創建新實體時提供所有必填字段和引用。我還讓存儲庫管理刪除操作,以確保強制執行所有驗證和完整性,以及審計記錄,并處理軟刪除場景。(活躍)


有些人回避使用 IQueryable,因為它會將 EF 主義“泄漏”到控制器中。然而,它泄露它們只不過是傳遞表達式以試圖抽象出 EF 的復雜方法。每個條件表達式都同樣容易需要符合 EF-isms。(即傳遞引用實體上的私有方法或靜態方法的 order-by 表達式)


像這樣的存儲庫模式(相對于只讓代碼訪問 DbSet)的好處是易于測試。模擬存儲庫只需要返回 aList<T> AsQueryable并且您的控制器等可以單獨測試。它還為所需的過濾器和針對實體的操作提供了很好的集中化。


查看完整回答
反對 回復 2022-07-10
  • 3 回答
  • 0 關注
  • 102 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號