存储库设计问题

时间:2009-11-06 17:08:57

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

我认为我正在进行的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);

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

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

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

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

4)使用现有设计我必须致电: TrainingCenterBusinessLayer.Save(); PersonBusinessLayer.Save(); 我觉得这是错的! save()操作应该在DataContext中调用一次。但是怎么样? (显然,如果解决上述问题,这可以解决)。

2 个答案:

答案 0 :(得分: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/

答案 1 :(得分:0)

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

DataContext可以传递,但也许有点沉重。更好的选择IMO将是IDbConnection

连接字符串实际上不是依赖项,它是用于初始化依赖项的特定实现的参数。

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