2010-07-06 91 views
2

我正在尋找一種方式來公開通過WCF數據服務我現有的業務層的一個子集(這是基於LinqToSql),以便通過WCF數據服務公開LinqToSQL業務層

  1. 數據服務由於我的業務層隨着時間的推移而發生變化,仍然可以由舊的odata客戶端使用(讀取和寫入)。看來唯一的方法就是確保數據服務不會改變,即使業務層發生了變化。

  2. 我的業務對象的一些屬性是隱藏的。

  3. 的數據服務可以處理比較大(數以萬計的企業實體)數據庫

  4. 它並不需要我幾個星期來實現數據服務

我已經試過了幾不同的方法,但他們每個人都有相當大的缺點。任何指導我忽視的東西將不勝感激。

這是到目前爲止,我已經試過的方法:

第一種方法:基於反射提供商實現IUpdateable,業務對象實現一個定義良好的接口

而不是暴露我的LinqToSQL直接對象,我試圖讓他們實現一個接口,該接口定義了我想要公開的屬性並僅公開該數據服務上的接口。例如,如果我有一個客戶LINQ的實體,我把它實現的ICustomer接口:

public interface ICustomer{ 
    int ID{get;set;} 
    string Name{get;set;} 
} 


//My Linq entity 
public partial class Customer: ICustomer{ 
    public int ID{get;set;} 
    public string Name{get;set;} 
    public string SomeOtherPropertyIDoNotWantToExpose{get;set;} 
} 

然後在我的數據服務提供者,我只是把房地產像

public IQueryable<ICustomer> Customers { 
     get { 
     //Note that the method below returns an IQueryable<Customer> 
     return MyBusinessLayerCustomersProvider.LoadAllCustomers(); 
     } 
    } 

可惜,這是行不通的。當試圖從客戶端訪問數據服務並使用任何依賴於OrderBy的Linq方法(如myContext.Customers.First())時,出現以下錯誤:

沒有泛型方法'OrderBy' System.Linq.Queryable'與提供的類型參數和參數兼容。如果方法是非泛型的,則不應提供類型參數。

我不知道爲什麼發生這種情況,但我堅持在這一點。

方法二:基於反射提供商實現IUpdateable,包裝類在我exising實體

在這種情況下,我試圖實現類在我的LINQ實體和數據服務暴露包裝類。喜歡的東西:

//My Linq entity 
    public partial class Customer 
    { 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string SomeOtherPropertyIDoNotWantToExpose { get; set; } 
    } 

    //the wrapper 
    public partial class WrappedCustomer 
    { 
    internal Customer _wrappedEntity; 
    public int ID { get{ return _wrappedEntity.ID;} set{ _wrappedEntity.ID = value;} } 
    public string Name { get { return _wrappedEntity.Name; } set { _wrappedEntity.Name = value; } } 
    } 

這種方法的問題是,這是行不通的,除非我加載所有客戶實體從我的數據庫中存儲的每個請求的數據服務。這是因爲在該客戶財產上的數據服務提供商的樣子:

public IQueryable<Customer> WrappedCustomer 
{ 
    get 
    { 
    IQueryable<WrappedCustomer> customers = from c in MyBusinessLayerCustomersProvider.LoadAllCustomers 
       select new WrappedCustomer{_wrappedEntity = c}; 

    //I am casting to list to avoid "no supported translation to sql" errors. 
    return tasks.ToList().AsQueryable(); 
    } 
} 

所以即使我的WCF數據服務的頁面大小限制爲100,上面的代碼將之前加載所有客戶的實體內存可以找到客戶實際想要加載的適當實體。所以這似乎沒有適當的比例。

第三條道路:直接暴露LinqToSQL實體,使用IgnoreProperties屬性

在這種情況下,我有我的數據服務回報從我的業務層直接發起linqtosql實體和使用IgnoreProperties屬性隱藏屬性我不想在數據層中公開。此方法可擴展且易於實現,但不支持正確版本化數據服務。例如,如果我想實現我的數據服務的第2版,那麼可能需要隱藏比第一個服務中更少的linq實體屬性。並且似乎沒有辦法在單個LinqToSQL實體上使用多個IgnoreProperties屬性。

第四種方法:實現自定義數據服務提供商

看來,自定義數據服務提供商可以很容易地覆蓋所有的我的要求。現在可能只是我,但這看起來太複雜了。看來我必須實現IDataServiceMetadataProvider,IDataServiceQueryProvider,IDataServiceUpdateProvider和IServiceProvider,這些都不重要。即使在閱讀Alex J's article series關於此主題並查看了odata網站上提供的示例之後,我仍然沒有得到實際需要實現的大部分功能。

實現IUpdateable似乎要複雜得多,特別是因爲我不知道樣本中提供的哪些代碼部分可以簡單地複製粘貼或需要定製。

第五種方法:使用EF並找到了一些方法,使既LINQ to SQL和EF

業務層的工作,我成功地實施了概念本的證明,但它是相當混亂的,所以我'd只能用這個作爲最後的手段。

那麼,我忽略了什麼?接下來我應該做什麼?我沒有時間了,所以任何建議將不勝感激。

感謝,

阿德里安

回答

1

看來,覆蓋所有的我的要求的唯一辦法是實現一個自定義數據服務提供商(see this thread)。這不是一個小任務,所以我決定現在使用反射提供程序+ IUpdateable實現,並在稍後出現需求(由於版本問題)時實現自定義數據服務提供程序。