9

我已經瀏覽了Repository模式,並且認識到我過去使用的一些想法讓我感覺很好。實體類與LINQ to SQL提供程序分離以實現Repository模式。怎麼樣?

但是現在我想編寫一個應用程序,使用這種模式但我想從實體庫提供者那裏獲得實體類DECOUPLODED

我想創建幾個組件:

  1. 一個「接口」組件,其將主辦常用接口包括IRepository接口
  2. 一個「實體」組件,其將主辦實體類如產品,用戶,訂單等。這個程序集將被「Interfaces」程序集引用,因爲有些方法會返回這些類型或它們的數組。另外它還會被主應用程序組件(如Web應用程序)引用一個或多個存儲庫提供程序組合件/組件。每個包括(至少)一個實現IRepository接口的類,並且它將與某個Data Store一起工作。數據存儲可能包括SQL Server,Oracle服務器,MySQL,XML文件,Web/WCF服務等。

研究LINQ to SQL在實現所有時間方面看起來非常高效,直到我發現生成的類和CustomDataContext類之間的深度依賴關係爲止。

如何在這種情況下使用LINQ to SQL?

+0

本博客文章提出了一個很好的解決方案。 http://iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and-the-Repository-Pattern.aspx – Riko 2009-08-21 13:30:37

+0

我已經實現了你所要求的,並將代碼發佈在我的博客:[一個通用的Linq到用於斷開連接的Linq到SQL數據層的SQL庫基類](http://devermind.com/linq/updated-generic-base-class-for-linq2sql-data-layers) – 2009-08-17 08:20:29

回答

6

我不知道這是否正是你想要的,但你可能想看看Rob Conery的MVC店面代碼。他使用linq提供程序使用存儲庫模式的變體。他將LINQ to Sql對象映射到域對象,然後將域對象從存儲庫提供程序返回到服務層,該服務層封裝了提供程序,允許他在返回到業務層之前返回數據的邏輯。

MVC Storefront Webcasts
Code

對我來說,這聽起來像你想的供應商返回的DTO,然後你要到的DTO在倉庫/業務層域對象映射。如果是這種情況,您可以將您的LINQ to SQL提供程序映射到DTO,讓它返回它們,然後將DTO映射到存儲庫/服務層中的域對象。這應該工作得很好,但它可能會變得乏味,因爲你現在有2個映射層。

在這種情況下,您將擁有: ProductService,它接受一個I​​ProductRepository。它喚起了IProductRepository中的方法來取回你的DTO。然後它將DTO映射到真實的業務對象並將它們返回給調用代碼。

+0

我剛進去看看MVC店面。它們使用不同於LINQ自動生成的域對象。所以我可能也會這樣做。感謝您指出這一點:) – 2008-10-25 23:17:29

1

不完全相同的情況,但我正在創建一個基於XML文件的自定義工具將生成一個OO模型。我的方法是在場景後面使用LINQ to SQL,並且由於我自動生成代碼,因此可以很容易地使用另一種機制來讓我們說MySQL數據源。由於不支持LINQ to SQL,因此您必須手動編寫數據訪問代碼,但使用OO模型的客戶端代碼將以任何方式更改。

+0

當然,如果我必須實現一個MySQL存儲庫提供者,我將自己編寫數據訪問代碼,對此沒有任何問題。然而,對於這個使用LINQ生成的實體不會尷尬嗎? – 2008-10-23 14:45:14

+0

我以前使用過DataSet,這是一個很好的解決方案。這可能不是最優雅的方式,但它肯定是有效的。 – Albert 2008-10-23 18:01:03

1

您的實體類可以實現將在「接口」程序集中聲明的IProduct,IUser,IOrder等接口嗎?這樣IRepository接口只引用業務對象接口(即返回IProduct的集合等),並且「接口」組合件與其他實現特定的組件分離。

2

您不必使用LINQ to SQL生成的代碼,您可以用必要的ColumnAttributes或使用外部XML映射文件來修飾自己的類。

5

您可以創建一個外部XML文件映射數據庫中任一類別:

<?xml version="1.0" encoding="utf-8"?> 
<Database Name="DbName" 
      xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007"> 
    <Table Name="DbTableName"> 
     <Type Name="EntityClassName" > 
      <Column Name="ID" Type="System.Int64" Member="Id" 
        DbType="BigInt NOT NULL IDENTITY" IsPrimaryKey="true" 
        CanBeNull="false" /> 
      <Column Name="ColumnName" Type="System.String" Member="PropertyA" 
        DbType="VarChar(1024)" CanBeNull="true" /> 
     </Type> 
    </Table> 
</Database> 

然後將XML傳遞給DataContext類:

using (var cn = GetDbConnection()) 
    { var mappingSrc = XmlMappingSource.FromReader(xmlReader); 

    using (var db = new DataContext(cn, mappingSrc)) 
    { var q = from entity in db.GetTable<EntityClassName>() 
       where entity.PropertyA = "..." 
       select entity.ID; 
    } 
    } 
2

最簡單的方法是將您的實體與datacontext分離開來:加載所需的實體,將其從DataContext中分離出來,然後使用它,然後使用Attach()將其與DataContext耦合以進行保存。

令人遺憾的是,LINQ沒有辦法將實體從數據上下文中分離出來,但是你可以克隆它們,這很好地工作。簡單的方法是這樣的:

public static T CloneEntity<T>(T source) 
{ 
    DataContractSerializer dcs = new DataContractSerializer(typeof(T)); 
    using (Stream stream = new MemoryStream()) 
    { 
    dcs.WriteObject(stream, source); 
    stream.Seek(0, SeekOrigin.Begin); 
    return (T)dcs.ReadObject(stream); 
    } 
} 
2

我與WCF

1類似的東西在您的DBML,設置你的序列化模式爲單向

2設置你的表中的所有列UpdateCheck的=假

3撰寫您的服務類似如下:

 
    public class Service1 : IService1 
    { 
     public Company GetCompany(int companyId) 
     { 
      using (DataClasses1DataContext dc = new DataClasses1DataContext()) 
      { 
       return (from c in dc.Companies where c.CompanyId == companyId select c).Single(); 
      } 
     }

public void SaveCompany(Company company) 
    { 
     using (DataClasses1DataContext dc = new DataClasses1DataContext()) 
     { 
      dc.Companies.Attach(company, true); 
      dc.SubmitChanges(); 
     } 
    } 

    public void InsertCompany(Company company) 
    { 
     using (DataClasses1DataContext dc = new DataClasses1DataContext()) 
     { 
      dc.Companies.InsertOnSubmit(company); 
      dc.SubmitChanges(); 
     } 
    } 
} 

4這個位置添加一個服務引用