对Linq to SQL和仓储模式感到困惑

4
在过去的4年中,我一直担任ASP.NET开发人员的职务,就职于一家小公司,该公司所有应用程序都使用.NET 2.0中的Smart UI反模式构建。这意味着我没有.NET 3.5的经验,也不了解LINQ等一般概念,如仓储和服务层。我意识到,为了找到新工作,我需要升级自己的知识水平,因此我开始阅读书籍、博客以及像this one这样的大量SO问题,并且现在是时候尝试使用我学到的内容构建一个简单的应用程序了。
我想建立一个小型应用程序来管理项目中的错误。
以下是我设计的非常基本的数据库架构图: The database
(来源: kristofclaes.be) 我已将此图转化为以下类(我省略了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相关联。这是否意味着我应该为聚合Project-Bug创建存储库?如果我想呈现所有错误列表,无论它们在哪个项目中,我该怎么办?我应该在我的IProjectsRepository中添加一个GetAllBugs()方法吗?还是应该为此使用单独的IBugsRepository?
我认为在这里创建单独的存储库可能会有其优势。根据我所了解的关于 Linq to SQL 的内容,您可以在 DataContext 上设置属性以指定如何处理惰性和急切加载。现在,当我获取项目列表或单个项目时,我希望急切地加载 Bug 列表。但我不想急切地加载该列表中每个 Bug 的 Project。但是,如果我想要加载所有 Bug(无论项目如何)或单个 Bug 的列表,则确实想要急切地加载 Project,但在这种情况下,我想要急切地加载该 Project 中的 Bug 列表。我的 Linq to SQL 知识非常有限,但这不是只能通过设置 DataContext 属性来实现的吗?这是否需要我为项目和错误分别拥有一个 DataContext 和两个存储库?除非有一种方法可以告诉 DataContext 急切地加载多达 2 层,并对任何更深层次的内容进行惰性加载?或者由于延迟执行,所有这些都不相关?请原谅我这么长而且可能并不清楚的问题,但所有这些新信息确实让我感到困惑。

(如果您喜欢评论我的数据库图表/类结构,请不要吝啬 :-))

1个回答

2
我个人只在L2S中使用存储库模式,如果我有获取数据库中存储数据的其他方法 - 这通常意味着我还有一组接口用于项目、错误等。
存储库模式对L2S来说是一个麻烦之处,因为它会使更新变得复杂 - 你从存储库传递一个对象(它打开和关闭了DataContext来获取它 - 你应该知道它们应该是短暂的),你修改它的属性并将其发送回进行更新 - 但你不能这样做,因为你需要原始的DataContext。你需要从新的数据上下文中再次获取对象,复制修改后的值,并更新第二个对象。
为了避免这种情况,你必须开始将数据上下文传递到你的存储库中进行大多数操作(让调用者确定数据上下文的生命周期);这会膨胀所有方法签名,让整个过程变得非常痛苦。
对我来说,L2S的美妙之处在于它的速度 - 所以当我看到人们不必要地包装DC时,我感到恐惧。
“不要误解我的意思 - 我正在编写一个系统,其中每个对象和“数据服务”都被抽象到接口后面;其中一些数据服务是使用Linq To Sql实现的;但这是因为整个系统旨在成为整个平台的热插拔后端。使用L2S有些棘手,但仍然可行。”
“其次 - 就您对急切加载和延迟加载的担忧而言 - 您通常会使用DataLoadOptions类和DC实例的“LoadOptions”成员来控制这一点。”
“如果您发现需要对哪些内容进行延迟和急切加载进行精细控制,则无需使用单独的DCs - 您只需将创建数据上下文的工作卸载到针对不同需求量身定制的不同方法中即可。”
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接