2011-03-28 79 views
1

我來自一個存儲過程並且手動創建數據訪問層的方法。我試圖理解我應該如何將Linq To SQL或實體框架納入我的正常計劃。我通常從DAL層分離出業務層,並在其間使用存儲庫。Entity Framework/Linq將sql模型轉換爲商業模型

似乎人們會使用從linq到sql的生成類,通過使用partial類擴展它們,或者執行完全分離並將生成的linq類映射到單獨的業務實體。我偏向於單獨的商業實體。但是,這似乎是違反直覺的。

我最近的一個項目使用了DDD和實體框架。當需要更新對象時,它將業務實體移動到複製層,當到達DAL層時,創建上下文而不是查詢對象。它會比更新價值和反思。

我沒有看到大點,因爲數據上下文未保存,並且需要額外的查詢才能在更新之前獲取對象。通常我會只是做了更新(如果併發不是問題)

所以我的問題歸結爲:

  1. 是否有意義,以單獨的LINQ to生成的類SQL轉換爲業務實體?
  2. 數據上下文應該保存還是不切實際?

謝謝你的時間,試圖讓我明白。我通常喜歡獨立出來,因爲即使在一些較小的項目中,它也使得它更易於理解。

回答

3

我目前手動推出我自己的Dto類和Datacontext,而不是使用從Linq到Sql的自動生成的代碼文件。爲了給出我的解決方案架構/建模背景,我有一個「合同」項目和一個「Dal」項目。 (也是一個「模型」項目,但我會盡力只關注Dal)。手動滾動我自己的Dtos和Datacontext,使所有事情變得更小更簡單,我將舉幾個例子來說明我如何在這裏做到這一點。

我從來沒有返回Dal以外的Dto對象,實際上我一定要聲明它們是內部的。我將它們退出的方式是將它們作爲接口(接口位於我的「合同」層)。我們將製作一個實現「IPersonRetriever和IPersonSaver」接口的簡單「PersonRepository」。

合同:

public interface IPersonRetriever 
{ 
    IPerson GetPersonById(Guid personId); 
} 

public interface IPersonSaver 
{ 
    void SavePerson(IPerson person); 
} 

達爾:

public class PersonRepository : IPersonSaver, IPersonRetriever 
    { 
     private string _connectionString; 

     public PersonRepository(string connectionString) 
     { 
      _connectionString = connectionString; 
     } 

     IPerson IPersonRetriever.GetPersonById(Guid id) 
     { 
      using (var dc = new PersonDataContext(_connectionString)) 
      { 
       return dc.PersonDtos.FirstOrDefault(p => p.PersonId == id); 
      } 
     } 

     void IPersonSaver.SavePerson(IPerson person) 
     { 
      using (var dc = new PersonDataContext(_connectionString)) 
      { 
       var personDto = new PersonDto 
       { 
        Id = person.Id, 
        FirstName = person.FirstName, 
        Age = person.Age 
       }; 

       dc.PersonDtos.InsertOnSubmit(personDto); 
       dc.SubmitChanges(); 
      } 
     } 
    } 

PersonDataContext:

internal class PersonDataContext : System.Data.Linq.DataContext 
    { 
     static MappingSource _mappingSource = new AttributeMappingSource(); // necessary for pre-compiled linq queries in .Net 4.0+ 

     internal PersonDataContext(string connectionString) : base(connectionString, _mappingSource) { } 

     internal Table<PersonDto> PersonDtos { get { return GetTable<PersonDto>(); } } 
    } 

    [Table(Name = "dbo.Persons")] 
    internal class PersonDto : IPerson 
    { 
     [Column(Name = "PersonIdentityId", IsPrimaryKey = true, IsDbGenerated = false)] 
     internal Guid Id { get; set; } 

     [Column] 
     internal string FirstName { get; set; } 

     [Column] 
     internal int Age { get; set; } 

     #region IPerson implementation 

     Guid IPerson.Id { get { return this.Id; } } 
     string IPerson.FirstName { get { return this.FirstName; } } 
     int IPerson.Age { get { return this.Age; } } 

     #endregion 
    } 

您需要將 「列」 屬性添加到您的所有DTO的屬性,但如果您注意到,如果您希望字段在界面上顯示的內容與您想要顯示的字段之間存在一對一的關係,實際表列的名稱,您不需要添加任何命名參數。在這個例子中,我在數據庫中的PersonId被存儲爲「PersonIdentityId」,但我只想讓我的界面將該字段設置爲「Id」。

這就是我如何做我的Dal層,我相信這層應該是愚蠢的,真正的愚蠢。愚蠢的是,它僅存在於CRUD(創建,檢索,更新和刪除)操作中。所有的業務邏輯將進入我的「模型」項目,這將消耗和利用IPersonSaver和IPersonRetriever接口。

希望這會有所幫助!

+0

這樣做更有意義。但我有這個問題,它是如何利用自動生成類的功能?看起來,如果你想有一個良好的分離,那麼仍然有很多管道工要做。 – Aur 2011-03-30 04:15:04

+0

如果你走這條路線,你確實需要做很多事情,這就是爲什麼我自己不使用自動生成的類。像這樣手動滾動它們使得我的觀點更容易閱讀,代碼更少,體積更小,更易於調試,更好的分離等。 – 2011-03-30 14:09:08

+0

因此,主要使用linq來幫助從存儲過程中抽象出來,並使得基本crud操作更容易。好吧,這很有意義。我一直在尋找泛型來試圖找出是否可以用來幫助減少代碼重複。 – Aur 2011-03-30 23:39:02