[.net] LINQ to SQL和存儲庫模式


Answers

這取決於DTO的定義以及如何測試。 如果您使用DBML,那麼LINQ to SQL想要在數據層中生成數據對象。 雖然LINQ to SQL 支持無知,但它不會讓事情變得簡單。 實體框架根本不支持它。

這意味著在標準模型中,您的數據層正在定義所有的域實體,如果您想要在與數據層真正隔離的情況下測試用戶界面/業務層,這是非常棘手的。

一個實用的方法可能是在單元測試中使用來自數據層的數據對象定義,而不是數據上下文(即隱藏存儲庫接口後面的數據上下文,但暴露實體類型) - 但這是混濁的水域一點點,並且意味著你的UI等需要強烈引用數據層。 但是如果你認為這是一個“域模型層,它恰好也包含了我們可能使用或者可能不使用的存儲庫實現”,那麼你可以證明它是正確的。

保持完全獨立的域實體使得單元測試和控制反轉 (IoC)更“純”,但增加了代碼量(所以是雙邊的)。

Question

我覺得我在圈子裡跑來跑去。 我似乎無法確定正確的存儲庫模式使用LINQ to SQL 。 如果您熟悉Rob Conery的 MVC店面,您將看到他的實現將LINQ生成的模型與另一個類包裝在一起,並將LINQ生成的模型簡單地視為數據傳輸對象 (DTO)。 它看起來像這樣:

//Custom wrapper class.
namespace Data
{
    public class Customer
    {
         public int Id {get;set;}
         public string Name {get;set;}
         public IList<Address> Addresses {get;set;}
    }
}

//Linq-Generated Class - severly abbreviated
namespace SqlRepository
{
    public class Customer
    {
         public int Id {get;set;}
         public string Name {get;set;}
         public EntitySet<Address> {get;set;}
    }
}

//Customer Repository
namespace SqlRepository
{
    public class UserRepository : IUserRepository
    {
        private _db = new DB(); //This is the Linq-To-Sql datacontext

        public IQueryable GetCusomters()
        {
            return
                from c in _db.Customers
                select new Customer // This is the wrapper class not the gen'd one
                {
                   Id = c.Id,
                   Name = c.Name,
                   Addresses = new LazyList(c.Addresses)
                };
        }

這樣做的好處是什麼(使用包裝類),而不是像Mike Hadlow在IRepository的版本中使用IRepository模式與LINQ to SQL一樣建立的方式<T>,他只是從中返回DTO對象庫?

業務邏輯應該在哪裡執行和檢查? 這是在一個單獨的層一起調用存儲庫保存/更新,或者它是內置到包裝類?