N层应用程序中的实体框架 - 懒惰加载与急切的加载模式
-
25-09-2019 - |
题
这个问题不能让我入睡,因为我想找到一个解决方案,但是……我的脑海中仍然没有发生任何事情。也许您可以帮助我,因为我认为这是一个非常普遍的问题。
我有一个N层应用程序:演示层,业务逻辑层,模型层。为简单起见,假设我的应用程序包含在演示层中,该表单允许用户搜索客户。现在,用户通过UI填充过滤器,然后单击一个按钮。发生了一些事情,请求到达演示层到类似的方法 CustomerSearch(CustomerFilter myFilter)
. 。现在,这个业务逻辑层使它变得简单:在模型上创建查询并恢复结果。
现在问题:您如何面对加载数据的问题?我的意思是,业务逻辑层不知道该特定方法将仅通过该形式调用。因此,我认为它不知道请求表格是否仅需要客户对象或带有链接订单实体的客户对象。
我尝试解释更好:我们的表格只想列出姓氏搜索的客户。它与订单无关。因此,业务逻辑查询将是类似的:
(from c in ctx.CustomerSet
where c.Name.Contains(strQry) select c).ToList();
现在这正常工作。两天后,您的老板要求您添加一张表格,让您像另一个一样搜索客户,并且需要显示每个客户创建的订单总数。现在我想重复使用该查询并添加附件的逻辑(包括)订单并取回它。
您将如何提出此请求?
这是我从那以后的最好的(我认为)的想法。我想收到您的来信:BLL中的我的客户搜索方法不会直接创建查询,而是通过私有扩展方法来构成对象图,例如:
private ObjectQuery<Customer> SearchCustomers(this ObjectQuery<Customer> qry, CustomerFilter myFilter)
和
private ObjectQuery<Customer> IncludeOrders(this ObjectQuery<Customer> qry)
但这并不能说服我,因为这似乎太复杂了。
谢谢,马可
解决方案
考虑转到DTO的演示层和业务层之间的接口,例如,请参见: - http://msdn.microsoft.com/en-us/magazine/ee236638.aspx
诸如AutoMapper之类的事情可以缓解与移动DTOS相关的许多痛苦,而此举将明确使您可以和无法处理查询结果,即如果它在DTO上已加载,则您不需要其他DTO 。
您当前的计划在演示层和数据层之间听起来太紧密了。
其他提示
我会同意Hightechrider关于使用DTO的评论,但是您对业务实体有一个有效的问题。
一种可能的解决方案(我正在开发的项目上使用这些行)是使用仅阅读的DTO(至少从演示层的角度来看。您的查询/获取操作只会返回DTOS,这将是给您懒惰的加载能力。
您可以设置业务层以返回可编辑的对象,该对象在更新/创建对象/实体时包装DTO。您的可编辑对象可以强制执行任何业务规则,然后将其保存/传递给业务层时,将其包装的DTO(带有更新的值)可以传递到数据层。
public class Editable
{
//.......initialize this, other properties/methods....
public bool CanEdit<TRet>(Expression<Func<Dto, TRet>> property)
{
//do something to determine can edit
return true;
}
public bool Update<TRet>(Expression<Func<Dto, TRet>> property, TRet updatedValue)
{
if (CanEdit(property))
{
//set the value on the property of the DTO (somehow)
return true;
}
return false;
}
public Dto ValueOf { get; private set;}
}
如果用户可以从业务层获得可编辑的对象,并允许业务对象执行如果用户有权编辑对象的特定属性,则可以实施实施。我在工作的域中遇到的一个常见问题是,有些用户可以编辑所有属性,而其他属性则不能,而任何人都可以查看属性的值。此外,演示层还可以确定确定按业务层指示和强制执行的用户所揭示的内容的能力。
我的另一个想法是,您的业务层不能公开可视化或以标准表达方式作为您传递到数据层的参数。例如,我有一个页面构建查询类似的内容:
public class PageData
{
public int PageNum;
public int TotalNumberPages;
public IEnumerable<Dto> DataSet;
}
public class BL
{
public PageData GetPagedData(int pageNum, int itemsPerPage, Expression<Func<Dto, bool>> whereClause)
{
var dataCt = dataContext.Dtos.Where(whereClause).Count();
var dataSet = dataContext.Dtos.Where(whereClause).Skip(pageNum * itemsPerPage).Take(itemsPerPage);
var ret = new PageData
{
//init this
};
return ret;
}
}