对Linq to SQL和存储库感到困惑

时间:2010-03-16 09:29:36

标签: linq-to-sql repository-pattern

在过去的4年里,我一直在一家小公司担任ASP.NET开发人员,所有应用程序都是使用.NET 2.0中的Smart UI反模式构建的。这意味着我没有使用.NET 3.5和LINQ以及存储库和服务层等一般概念的经验。我意识到,为了找到一份新工作,我需要升级我的知识,所以我开始阅读书籍,博客和许多诸如this one之类的问题,现在是时候尝试用一个简单的应用程序了我应该学到什么。

我想构建一个小型应用程序来管理项目中的错误。

这是我提出的非常基本的数据库图表:

The database http://www.kristofclaes.be/so/database.gif

我已将此图表转换为以下类(我省略了Linq to SQL属性):

class Project
{
    public int ID { get; internal set; }
    public string Name { get; set; }
    public string Description { get; set; }

    private EntitySet<Bug> bugs;
    public EntitySet<Bug> Bugs
    {
        get { return this.bugs; }
        set { this.bugs.Assign(value); }
    }
}

class Bug
{
    public int ID { get; internal set; }
    public string Summary { get; set; }
    public string Description { get; set; }

    private EntityRef<Project> belongsTo;
    public Project BelongsTo
    {
        get { return this.belongsTo.Entity; }
        set { this.belongsTo.Entity = value; }
    }

    private EntityRef<Person> currentStatusSetBy;
    public Person CurrentStatusSetBy
    {
        get { return this.currentStatusSetBy.Entity; }
        set { this.currentStatusSetBy.Entity = value; }
    }

    public Datetime CurrentStatusSetOn { get; set; }
    public BugStatus CurrentStatus { get; set; }

    private EntitySet<BugStatusHistory> previousStatuses
    public EntitySet<BugStatusHistory> PreviousStatuses
    {
        get { return this.previousStatuses; }
        set { this.previousStatuses.Assign(value); }
    }
}

class BugStatusHistory
{
    public int ID { get; internal set; }
    public DateTime StatusSetAt { get; set; }   
    public BugStatus Status { get; set; }

    private EntityRef<Person> statusSetBy;
    public Person StatusSetBy
    {
        get { return this.statusSetBy.Entity; }
        set { this.statusSetBy.Entity = value; }
    }
}

class Person
{
    public ID { get; internal set; }
    public string Name {get; set; }
    public string Email { get; set; }
    public string Login { get; set; }
    public string Password { get; set; }
}

enum BugStatus { New, Confirmed, Solved }

我已将这些类放在一个名为DomainModel的类库中,我想从ASP.NET MVC 2应用程序中引用该DomainModel。根据我的阅读,我还应该为我的DomainModel添加存储库甚至服务层。这让我很困惑。

我已经读过你不应该为每个类/表创建一个存储库,但是你应该为聚合(类组)创建一个存储库。如果实体不能存在于另一个实体的上下文之外,则它不应该有自己的存储库。在我的示例中,Bug始终链接到项目。这是否意味着我应该为聚合Project-Bug创建一个存储库?如果我想呈现所有错误的列表,无论它们是什么项目,该怎么办?我应该将方法GetAllBugs()添加到我的IProjectsRepository吗?或者我应该为这种用法创建一个单独的IBugsRepository吗?

我认为创建单独的存储库可以在这里发挥其优势。从我读过的关于Linq到SQL的内容,您可以在DataContext上设置一个属性,以指定如何处理延迟和急切加载。现在,当我得到一个Projects列表或一个Project时,我想急切地加载Bugs列表。但我不想急切地加载该列表中每个Bug的项目。但是,如果我想加载所有错误列表(无论是项目)还是单个Bug,我 想要急切加载项目,但在这种情况下我 想要急切地加载该项目中的错误列表。我的Linq to SQL knowlegde非常有限,但这不是只能通过设置DataContext属性来实现的吗?这不是要求我有一个DataContext用于Projects和一个DataContext for Bugs,因此需要两个存储库吗?除非它以某种方式告诉DataContext急切地加载最多2个级别并且对更深层次的任何事情进行延迟加载?或者由于延期执行,所有这些都无关紧要?

请原谅我长期以来的长期问题(可能甚至不是那么清楚),但所有这些新信息真让我感到困惑。

(我喜欢评论我的数据库图表/类结构,请不要饶恕我: - )

1 个答案:

答案 0 :(得分:2)

如果我有替代方法来获取存储在数据库中的数据,我个人只使用L2S的存储库模式 - 这通常意味着我还有一组Project,Bug等接口。

存储库模式是L2S的漏洞,因为它使更新变得复杂 - 你从存储库中传出一个对象(打开并关闭一个DataContext来获取它 - 它们应该是你看到的短暂存在),你修改它的属性并将其重新发送以进行更新 - 但您不能,因为您需要原始的DataContext。您需要从新数据上下文再次获取对象,复制修改后的值,然后更新第二个。

为避免这种情况,您必须开始将数据上下文传递到存储库以进行大多数操作(让调用者确定数据上下文的生命周期);它会使你所有的方法签名膨胀,并在a * s中造成全面的痛苦。

对于我来说,L2S的美妙之处在于它的速度 - 所以当我看到人们为了它而不必要地包装DC时,我会不寒而栗。

不要误会我的意思 - 我正在编写一个系统,当时每个对象和'数据服务'都被抽象出接口;其中一些数据服务是使用Linq To Sql实现的;但这是因为整个系统旨在成为整个平台的热插拔后端。使用L2S一直很棘手,但它仍然可行。

其次 - 就您对急切和延迟加载的担忧而言 - 您通常会使用DC实例的DataLoadOptions class和'LoadOptions'成员来控制它。

如果您发现需要对哪些内容进行细粒度控制以实现懒惰和急切负载,那么您不需要单独的DC - 您只需将datacontext的创建卸载到针对不同需求而定制的不同方法:

public MyDataContext GetDCForProjects()
{
  var DC = new MyDataContext();
  DataLoadOptions dlo = new DataLoadOptions();
  dlo.LoadWith<Project>(p => p.Bugs);
  DC.LoadOptions = dlo;
  return DC;
}

//add more methods for the different needs