存储库设计问题

发布于 2024-08-10 05:13:57 字数 2263 浏览 4 评论 0 原文

我认为我正在进行的 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(温莎,使用生活方式=“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不可用(因为有不同的 DataContext,对吧?)。如何克服这个?!?

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

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

I think i have some design errors in my ongoing web project (i'm using Linq2SQL implementing repository pattern)
1) Every repository creates its own DataContext (is this correct?should this be this way)
For example:

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
}

and another example:

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        
}

As you can figure out i'm using IoC (Windsor, using lifestyle="PerWebRequest").

2) Using a services layer for every repository. E.g. for persons

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)
} 

Is this the correct way of defining a services layer? Or should i use one service class which references all the repositories?

3) There is a relation between personTable and trainingCenterTable. Every time i insert something into the TrainingCenter-Service i must also insert one record into the Person-Service. So the solution to this is to say :

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

Of course i want these two insertions happening in Transactional manner, so i decide to wrap this statements in

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

So there arises a new problem: MSDTC on server '.\SQLEXPRESS' is unavailable(because there are different DataContexts,right??). How to overcome this?!?

A solution would be to create the DataContext externally and pass it as a parameter to the repository!?? Correct thinking? But how to implement?

4)With the existing design i have to call:
TrainingCenterBusinessLayer.Save();
PersonBusinessLayer.Save();
i think this is wrong! The save() operation should be called once in the DataContext. But how? (apparently this can be solved if the above point is solved).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

咿呀咿呀哟 2024-08-17 05:13:57

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

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

Linq to sql 多数据上下文在同一交易中

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

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

I was having a similar issue to yourself. The way I solved it was by passing a DataContext into my repositories. I then used StructureMap to create one instance of the DataContext per web request.

You may find the following posts interesting:

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/

你好,陌生人 2024-08-17 05:13:57

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

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

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

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

If you're doing full-on DI, you should try to pass around an abstraction (interface) as the dependency. That way, if you want to mock it, you can easily swap out its implementation.

DataContext is OK to pass around, but perhaps a bit heavy. A better choice IMO would be IDbConnection.

A connection string is not really a dependency, it's a parameter used to initialize a specific implementation of a dependency.

There's also the MvcFakes approach with IDataContext and context wrapper, but I find that to be a pain. As long as your DataContext instances share the same connection instance, you won't need a distributed transaction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文