在过去的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个级别并且对更深层次的任何事情进行延迟加载?或者由于延期执行,所有这些都无关紧要?
请原谅我长期以来的长期问题(可能甚至不是那么清楚),但所有这些新信息真让我感到困惑。
(我喜欢评论我的数据库图表/类结构,请不要饶恕我: - )
答案 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