linq-to-sql – 对Linq to SQL和存储库感到困惑

在过去的4年里,我一直在一家小公司担任ASP.NET开发人员,所有应用程序都是使用.NET 2.0中的Smart UI反模式构建的.这意味着我没有使用.NET 3.5和LINQ以及存储库和服务层等一般概念的经验.我意识到,为了找到一份新工作,我需要升级我的知识,所以我开始阅读书籍,博客和许多SO问题,如
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个级别并且对更深层次的任何事情进行延迟加载?或者由于延期执行,所有这些都无关紧要?

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

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

最佳答案 我个人只使用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
点赞