9

我查看了存储库模式,我发现了一些我过去使用的想法,这些想法让我感觉很好。

但是现在我想编写一个使用这种模式的应用程序,但我希望实体类与存储库提供者分离。

我会创建几个程序集:

  1. 一个“接口”程序集,它将承载包括 IRepository 接口在内的通用接口
  2. 一个“实体”程序集,它将承载产品、用户、订单等实体类。该程序集将由“接口”程序集引用,因为某些方法将返回此类类型或它们的数组。它也将被主应用程序程序集(例如 Web 应用程序)引用
  3. 一个或多个存储库提供程序程序集/程序集。每个都将包括(至少)一个实现 IRepository 接口的类,并且它将与某个数据存储一起使用。数据存储可以包括 SQL Server、Oracle 服务器、MySQL、XML 文件、Web/WCF 服务等。

在我发现生成的类和 CustomDataContext 类之间存在深度依赖之前,研究 LINQ to SQL 看起来在实现所有方面所花费的时间方面看起来非常有成效。

在这种情况下如何使用 LINQ to SQL?

4

9 回答 9

6

我不知道这是否正是您想要的,但您可能想看看 Rob Conery 的 MVC Storefront 代码。他将存储库模式的变体与 linq 提供程序一起使用。他将 LINQ to Sql 对象映射到域对象,然后将域对象从存储库提供者返回到服务层,该服务层包装提供者,允许他在返回的数据到达业务层之前对其进行一些逻辑处理。

MVC 店面网络广播
代码

对我来说,听起来您希望提供者返回 DTO,然后您希望将 DTO 映射到存储库/服务层中的域对象。如果是这种情况,您可以将 LINQ to SQL 提供程序映射到 DTO,让它返回它们,然后将 DTO 映射到存储库/服务层中的域对象。这应该可以正常工作,但它可能会变得乏味,因为您现在将有 2 个映射层。

在这种情况下,您将拥有:ProductService,它采用 IProductRepository。它调用 IProductRepository 上的方法来取回您的 DTO。然后它将 DTO 映射到真实的业务对象,并将它们返回给调用代码。

于 2008-10-23T15:56:22.540 回答
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;
     }
  }
于 2008-10-24T07:33:33.397 回答
4

我在这里找到了一篇很棒的博客文章(有很多好的代码):http: //iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and-the-Repository-Pattern.aspx

于 2009-04-12T12:05:48.967 回答
3

我认为您需要 POCO(普通旧 CLR 对象)支持。LINQ to SQL 有一个名为Close2Poco的适配器。

但我建议切换到实体框架,目前他们也有一个POCO 适配器,但在v2 中,它预计会得到开箱即用的支持

于 2008-10-24T08:03:41.963 回答
2

您不必使用 LINQ to SQL 生成的代码,您可以使用必要的 ColumnAttributes 装饰您自己的类或使用外部 XML 映射文件。

于 2008-10-24T06:54:40.793 回答
2

最简单的方法是将您的实体与数据上下文分离:加载所需的实体,将其与 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);
  }
}
于 2008-10-24T08:19:29.513 回答
2

我用 WCF 做了类似的事情

1 在您的 DBML 上,将您的序列化模式设置为单向

2 将表上的所有列设置为 UpdateCheck=false

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 添加服务引用

于 2008-10-24T17:48:39.867 回答
1

不完全相同的场景,但我正在努力创建一个基于 XML 文件将生成 OO 模型的自定义工具。我的方法是在幕后使用 LINQ to SQL,因为我是自动生成代码的,所以可以很容易地使用另一种机制来假设 MySQL 数据源。由于 LINQ to SQL 不支持它,您将不得不手动编写数据访问代码,但是将使用 OO 模型的客户端代码会以任何方式发生变化。

于 2008-10-23T13:59:12.697 回答
1

您的实体类能否实现将在“接口”程序集中声明的 IProduct、IUser、IOrder 等接口?这样,IRepository 接口仅引用业务对象接口(即返回 IProduct 等的集合),并且“接口”程序集与您的其他特定于实现的程序集分离。

于 2008-10-23T14:50:51.113 回答