2010-12-07 42 views
1

最近,我們的EF架構已經遷移到此。我正在尋找關於如何最好地改變它(或不是)的建議。數據架構

我們有一個「數據」項目,該項目包含了我們DataModel.EDMX文件,它返回我們的實體對象一個Context.cs類一起:

public static DataModelEntities getContext() {   
    return new DataModelEntities(); 
} 

然後,我們創建一個「業務」項目,該項目包含近EF生成的類的副本。例如,如果我們有一個客戶表,我們創建了一個CustomerBO類來保存屬性:

public class CustomerBO { 
    public int customerId {get;set;} 
    public string firstName {get;set;} 
    public string lastName {get;set;} 
    public int orderCount {get;set;} 
} 

我們在理論上可以使用由EF創建Customer類,但我們不這樣做,因爲它通常包含如果我們最終將其序列化並通過網絡傳遞,則會有很多額外的東西。

在我們的CustomerBO類中,我們有檢索/保存數據的方法。例如,getCustomerList方法:

public static List<CustomerBO> getCustomers() { 
    using (var context = Context.getContext()) { 
     var lst = from c in context.Customers 
        select c; 

     // Wrap the EF results to a List<Customer> 
     return toCustomerList(lst); 

    } 
} 

/// Wraps a queryable object to a List<Customer> 
private static List<CustomerBO> toCustomerList(IEnumerable<Customer> queryCustomerData) { 
    var data = from c in queryCustomerData 
       select new CustomerBO() { 
        customerId = c.customerId, 
        firstName = c.firstName, 
        lastName = c.lastName, 
        orderCount = c.CustomerOrders.Count() 
       }; 

    return data.ToList(); 
} 

我們始終確保使用toCustomerList方法將所有數據返回到GUI。它向我們保證會設置任何自定義屬性,如orderCount,並且不要求開發人員記住將這些自定義屬性添加到主EF查詢中。

總的來說,設計是堅實的,並已解決了多年來我們碰到的許多問題。但是,有一個特別的問題困擾我。我們稱之爲「業務」層,但我們在其中有一些「查詢」邏輯。有沒有更好的方法來設計這個模式,以符合既定的模式,並仍然達到相同的結果?

回答

1

您的設計看起來相當合理。

我會做一個評論 - 儘量不要使用靜態輔助方法進行數據檢索,並儘量不要將它們放在DTO類(例如CustomerBO)中。

爲什麼不在數據項目中創建存儲庫?

稱它爲CustomerRepository,它的響應能力是將業務查詢轉換成EF查詢,並將結果投影到DTO中。

更簡單的方法 - 你保持你的DTO的好和薄,他們不應該有任何邏輯。另外,如果您瞭解延遲執行和延遲加載的風險,則可以從您的存儲庫返回IQueryable<T>,並從業務層返回具體集合(例如ICollection<T>) - 這是我們爲實現最大靈活性所做的工作。所有的邏輯(查詢/業務)都在我們的業務/服務層。

您的具有查詢邏輯的「業務」層沒有錯 - 我們也是這樣做的。我們在業務層建立查詢並傳遞到我們的存儲庫。

您可以使用的唯一模式是CQRS - 您可以在「命令」中分隔「查詢」。

然而這是一個非常繁瑣/涉及的架構。

我認爲將您的DAL代碼抽象到存儲庫中就足夠了。

HTH。

EDIT

這裏是一個非常簡單的IQueryable<T>庫例如:

CustomerRepository

public class CustomerRepository 
{ 
    private MyDataContext _ctx; 

    public CustomerRepository(MyDataContext ctx) 
    { 
     this._ctx = ctx; 
    } 

    public IQueryable<Order> FindOrders() 
    { 
     return _ctx.Orders; 
    } 
} 

CustomerDomainService

public class CustomerDomainService 
{ 
    public ICollection<Order> GetOrdersForCustomer(int customerId) 
    { 
     // You should in reality use interfaces and dependency injection here.. 
     CustomerRepository repo = new CustomerRepository(new MyContext()); 
     var orders = repo.FindOrders().Where(x => x.CustomerId == customerId).ToList(); 
    } 
} 

正如我所說,要非常小心與IQueryable存儲庫。只有推遲查詢到您的域名服務,而不是更晚。此外,只有您的域名服務應該引用存儲庫。

因此,您的演示文稿請​​求來自您的域服務的數據,該數據將針對存儲庫進行查詢並返回結果。

+0

因此,當我使用CustomerRepository時,基本上是將getCustomers()方法從我的DTO類移出到CustomerRepository類中 - 仍然是靜態方法?我有興趣瞭解更多關於你對Iqueryable/ICollection觀點的信息 - 你知道一篇好文章嗎? – bugfixr 2010-12-09 22:59:08

0

我想你可以使用EF實體(如果你說你的版本幾乎是重複的),並且只需用你需要的額外功能對它們進行部分的類化處理,比如通過線路發送它們的序列化。 我沒有看到任何問題。每次你更新你的edmx你的部分類將保持不變。