【问题标题】:Repository design problems存储库设计问题
【发布时间】:2009-11-06 17:08:56
【问题描述】:

我认为我正在进行的 Web 项目中存在一些设计错误(我正在使用 Linq2SQL 实现存储库模式) 1)每个存储库都创建自己的 DataContext(这是正确的吗?应该这样吗) 例如:

public class SQLPersonRepository : IPersonRepository
{
    DataContext dc;

    public SQLPersonRepository(string connectionString)
    {

        dc = new DataContext(connectionString, Mapping.GetMapping());

        personTable = (dc).GetTable<Person>();
        personRoleTable = (dc).GetTable<PersonRole>();
        roleTable = (dc).GetTable<Role>();

    }
    Get Method 
    Add Methods for the different Tables
    Save Method
}

还有一个例子:

class SQLTrainingCenterRepository:ITrainingCenterRepository
    {
        DataContext dc;
        private Table<Trainingcenter> trainingCenterTable;

    public SQLTrainingCenterRepository(string connectionString)
        {            
            dc = new DataContext(connectionString, Mapping.GetMapping());

            trainingCenterTable = (dc).GetTable<Trainingcenter>();            
        } 

        Get Methods
        Add Method
        Save Method        
}

如你所见,我正在使用 IoC(Windsor,使用 Lifestyle="PerWebRequest")。

2) 为每个存储库使用服务层。例如。对于人

public class PersonBusinessLayer
{
    IPersonRepository personRepository;

    public PersonBusinessLayer(IPersonRepository personRepository)
    {
        this.personRepository = personRepository;

    }
  ...  diverse Get Methods
    Add Method   (wrapper around repository.Add)
    Save Method  (wrapper around repository.Save)
} 

这是定义服务层的正确方法吗?还是应该使用一个引用所有存储库的服务类?

3) personTable 和 trainingCenterTable 之间存在关系。每次我在 TrainingCenter-Service 中插入一些东西时,我还必须在 Person-Service 中插入一条记录。所以解决这个问题的方法是:

TrainingCenterBusinessLayer.Insert(trainingCenter);
PersonBusinessLayer.Insert(person);

当然我希望这两个插入以事务方式发生,所以我决定将这些语句包装在

using (TransactionScope scope = new TransactionScope())
{
...
}

所以出现了一个新问题:服务器'.\SQLEXPRESS' 上的MSDTC 不可用(因为有不同的DataContexts,对吗??)。如何克服这个?!?

解决方案是在外部创建 DataContext 并将其作为参数传递给存储库!??正确的想法?但是如何实现呢?

4) 使用现有设计,我必须调用: TrainingCenterBusinessLayer.Save(); PersonBusinessLayer.Save(); 我认为这是错误的! save() 操作应在 DataContext 中调用一次。但是怎么做? (显然解决了上述问题就可以解决)。

【问题讨论】:

    标签: c# sql-server linq-to-sql repository-pattern transactionscope


    【解决方案1】:

    我和你自己也有类似的问题。我解决它的方法是将 DataContext 传递到我的存储库中。然后,我使用 StructureMap 为每个 Web 请求创建一个 DataContext 实例。

    您可能会发现以下帖子很有趣:

    Linq to sql multiple data context in same transaction

    http://www.west-wind.com/weblog/posts/246222.aspx

    http://blog.codeville.net/2007/11/29/linq-to-sql-the-multi-tier-story/

    【讨论】:

      【解决方案2】:

      如果您正在执行全面的 DI,您应该尝试传递一个抽象(接口)作为依赖项。这样,如果你想模拟它,你可以轻松地换掉它的实现。

      DataContext 可以通过,但可能有点重。更好的选择 IMO 是 IDbConnection

      连接字符串并不是真正的依赖,它是一个用于初始化依赖的具体实现的参数。

      还有带有IDataContext 和上下文包装器的MvcFakes 方法,但我发现这很痛苦。只要您的DataContext 实例共享相同的连接实例,您就不需要分布式事务。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-04
        • 2011-01-12
        • 2011-09-27
        • 2011-07-07
        • 1970-01-01
        相关资源
        最近更新 更多