Linq 存储库与数据访问 在n-层应用程序的上下文中,你认为你的数据访问类和你的存储库之间有什么区别?
我倾向于认为是的,但我只是想看看其他人的想法。我的想法是,存储库的工作只是包含和执行原始查询本身,其中数据访问类将创建上下文,执行存储库(在上下文中传递),处理数据模型到域模型的映射,并返回备份结果 你们觉得怎么样?在Linq到XML的场景中,您是否也看到了这些变化(假设您更改了相关XDocument的上下文) 安东尼干杯 更新: 这是我以前通常采用的实现方式:Linq 存储库与数据访问 在n-层应用程序的上下文中,你认为你的数据访问类和你的存储库之间有什么区别?,linq,linq-to-sql,linq-to-xml,repository-pattern,Linq,Linq To Sql,Linq To Xml,Repository Pattern,我倾向于认为是的,但我只是想看看其他人的想法。我的想法是,存储库的工作只是包含和执行原始查询本身,其中数据访问类将创建上下文,执行存储库(在上下文中传递),处理数据模型到域模型的映射,并返回备份结果 你们觉得怎么样?在Linq到XML的场景中,您是否也看到了这些变化(假设您更改了相关XDocument的上下文) 安东尼干杯 更新: 这是我以前通常采用的实现方式: public class TermBl : ITermBl { public IEnumerable<ITerm>
public class TermBl : ITermBl
{
public IEnumerable<ITerm> GetAll(IListParameter criteria)
{
//Any pre business logic
var dataLayer = this.CreateDataLayer();
var result = dataLayer.GetAll(criteria);
//Any post business logic
return result;
}
... Other methods
}
public class TermDa : ITermDa
{
public IEnumerable<ITerm> GetAll(IListParameter criteria)
{
//Linq query
var dataResult = ....ToList()
var mappedResult = this.FromDataToDomain(dataResult);
//Note the mapping isn't done in this object, the actual
// mapping is handled by a separate component
return mappedResult;
}
... Other methods
}
公共类术语:ITERML
{
公共IEnumerable GetAll(IListParameter标准)
{
//任何业务前逻辑
var dataLayer=this.CreateDataLayer();
var result=dataLayer.GetAll(标准);
//任何后业务逻辑
返回结果;
}
…其他方法
}
公共类术语:ITermDa
{
公共IEnumerable GetAll(IListParameter标准)
{
//Linq查询
var dataResult=…ToList()
var mappedResult=this.FromDataToDomain(dataResult);
//注意,映射不是在这个对象中完成的,而是实际的
//映射由单独的组件处理
返回映射结果;
}
…其他方法
}
您是否看到了该模式在总体上存在的任何固有问题
对于我一直在考虑使用it的存储库,而不是直接在TermDa的GetAll方法中使用查询,我将对其进行更改,使其看起来更像这样:
public class TermDa : ITermDa
{
public IEnumerable<ITerm> GetAll(IListParameter criteria)
{
var repository = this.CreateRepository();
var dataResult = repository.GetAll(..., criteria).ToList();
var mappedResult = this.FromDataToDomain(dataResult);
return mappedResult;
}
... Other methods
}
public class TermRepository : ITermRepository
{
public IQueryable<ITerm> GetAll(IMyContext context, IListParameter criteria)
{
//Linq query
return ...;
}
... Other queries
}
公共类TermDa:ITermDa
{
公共IEnumerable GetAll(IListParameter标准)
{
var repository=this.CreateRepository();
var dataResult=repository.GetAll(…,criteria).ToList();
var mappedResult=this.FromDataToDomain(dataResult);
返回映射结果;
}
…其他方法
}
公共类术语库:ITermRepository
{
公共IQueryable GetAll(IMyContext上下文,IListParameter条件)
{
//Linq查询
返回。。。;
}
……其他问题
}
你们是这么认为的吗?还是真的。。。无论是否使用存储库,我都可以看到上述两种方法完全保护业务层不了解所使用的任何数据访问方法/技术…是的,这两种方法有很大区别
- DAL(如表数据网关)是一种数据库概念。它负责向数据库发出查询并返回记录集
- 存储库是一个域概念。它负责接受结构化请求并返回强类型对象
更新:
public interface IOrderData
{
IDataReader GetOrder(int orderID);
}
public interface IOrderDetailData
{
IDataReader GetOrderDetails(int orderID);
}
public interface IProductData
{
IDataReader GetProduct(int productID);
}
public class Order
{
public int ID { get; set; }
public DateTime Date { get; set; }
public OrderStatus Status { get; set; }
// etc.
public IList<OrderDetail> Details { get; set; }
}
public class OrderDetail
{
public int ID { get; set; }
public Product Product { get; set; }
public int Quantity { get; set; }
}
public interface IDataMapper
{
Order MapOrder(IDataRecord record);
OrderDetail MapOrderDetail(IDataRecord record);
Product MapProduct(IDataRecord record);
}
public interface IOrderRepository
{
Order GetOrder(int orderID);
}
public class OrderRepository
{
// These get initialized in the constructor
private readonly IOrderData orderData;
private readonly IOrderDetailData orderDetailData;
private readonly IProductData productData;
private readonly IDataMapper mapper;
public Order GetOrder(int orderID)
{
Order order;
using (IDataReader orderReader = orderData.GetOrder(orderID))
{
if (!orderReader.Read())
return null;
order = mapper.MapOrder(orderReader);
}
using (IDataReader detailReader =
orderDetailData.GetOrderDetails(orderID))
{
while (detailReader.Read())
{
OrderDetail detail = mapper.MapOrderDetail(detailReader);
detail.Product = ...; // Omitted for brevity, more reading/mapping
order.Details.Add(detail);
}
}
return order;
}
}
这个问题似乎反映了大量的混乱,所以让我试着用一个代码示例来澄清。如果您不使用任何ORM,而是自己进行映射,那么您可能会使用以下设计。这些都不是产品质量代码,只是出于教育目的:
数据访问:
public interface IOrderData
{
IDataReader GetOrder(int orderID);
}
public interface IOrderDetailData
{
IDataReader GetOrderDetails(int orderID);
}
public interface IProductData
{
IDataReader GetProduct(int productID);
}
public class Order
{
public int ID { get; set; }
public DateTime Date { get; set; }
public OrderStatus Status { get; set; }
// etc.
public IList<OrderDetail> Details { get; set; }
}
public class OrderDetail
{
public int ID { get; set; }
public Product Product { get; set; }
public int Quantity { get; set; }
}
public interface IDataMapper
{
Order MapOrder(IDataRecord record);
OrderDetail MapOrderDetail(IDataRecord record);
Product MapProduct(IDataRecord record);
}
public interface IOrderRepository
{
Order GetOrder(int orderID);
}
public class OrderRepository
{
// These get initialized in the constructor
private readonly IOrderData orderData;
private readonly IOrderDetailData orderDetailData;
private readonly IProductData productData;
private readonly IDataMapper mapper;
public Order GetOrder(int orderID)
{
Order order;
using (IDataReader orderReader = orderData.GetOrder(orderID))
{
if (!orderReader.Read())
return null;
order = mapper.MapOrder(orderReader);
}
using (IDataReader detailReader =
orderDetailData.GetOrderDetails(orderID))
{
while (detailReader.Read())
{
OrderDetail detail = mapper.MapOrderDetail(detailReader);
detail.Product = ...; // Omitted for brevity, more reading/mapping
order.Details.Add(detail);
}
}
return order;
}
}
域:
public interface IOrderData
{
IDataReader GetOrder(int orderID);
}
public interface IOrderDetailData
{
IDataReader GetOrderDetails(int orderID);
}
public interface IProductData
{
IDataReader GetProduct(int productID);
}
public class Order
{
public int ID { get; set; }
public DateTime Date { get; set; }
public OrderStatus Status { get; set; }
// etc.
public IList<OrderDetail> Details { get; set; }
}
public class OrderDetail
{
public int ID { get; set; }
public Product Product { get; set; }
public int Quantity { get; set; }
}
public interface IDataMapper
{
Order MapOrder(IDataRecord record);
OrderDetail MapOrderDetail(IDataRecord record);
Product MapProduct(IDataRecord record);
}
public interface IOrderRepository
{
Order GetOrder(int orderID);
}
public class OrderRepository
{
// These get initialized in the constructor
private readonly IOrderData orderData;
private readonly IOrderDetailData orderDetailData;
private readonly IProductData productData;
private readonly IDataMapper mapper;
public Order GetOrder(int orderID)
{
Order order;
using (IDataReader orderReader = orderData.GetOrder(orderID))
{
if (!orderReader.Read())
return null;
order = mapper.MapOrder(orderReader);
}
using (IDataReader detailReader =
orderDetailData.GetOrderDetails(orderID))
{
while (detailReader.Read())
{
OrderDetail detail = mapper.MapOrderDetail(detailReader);
detail.Product = ...; // Omitted for brevity, more reading/mapping
order.Details.Add(detail);
}
}
return order;
}
}
存储库:
public interface IOrderData
{
IDataReader GetOrder(int orderID);
}
public interface IOrderDetailData
{
IDataReader GetOrderDetails(int orderID);
}
public interface IProductData
{
IDataReader GetProduct(int productID);
}
public class Order
{
public int ID { get; set; }
public DateTime Date { get; set; }
public OrderStatus Status { get; set; }
// etc.
public IList<OrderDetail> Details { get; set; }
}
public class OrderDetail
{
public int ID { get; set; }
public Product Product { get; set; }
public int Quantity { get; set; }
}
public interface IDataMapper
{
Order MapOrder(IDataRecord record);
OrderDetail MapOrderDetail(IDataRecord record);
Product MapProduct(IDataRecord record);
}
public interface IOrderRepository
{
Order GetOrder(int orderID);
}
public class OrderRepository
{
// These get initialized in the constructor
private readonly IOrderData orderData;
private readonly IOrderDetailData orderDetailData;
private readonly IProductData productData;
private readonly IDataMapper mapper;
public Order GetOrder(int orderID)
{
Order order;
using (IDataReader orderReader = orderData.GetOrder(orderID))
{
if (!orderReader.Read())
return null;
order = mapper.MapOrder(orderReader);
}
using (IDataReader detailReader =
orderDetailData.GetOrderDetails(orderID))
{
while (detailReader.Read())
{
OrderDetail detail = mapper.MapOrderDetail(detailReader);
detail.Product = ...; // Omitted for brevity, more reading/mapping
order.Details.Add(detail);
}
}
return order;
}
}
现在这更有意义了吗?DAL正在处理数据。具体存储库可以封装数据访问类,但抽象存储库(其公共接口)只处理域类
我将再次提醒读者,这甚至还不接近于产品质量代码,而且今天的大多数应用程序都使用ORM或至少某种更好的自动映射形式。这仅用于说明目的。您似乎对它有很好的把握。“数据访问类”可以有很多不同的形状。它是一种与数据访问有关的类。您的存储库是(A)处理数据持久性的模式,以及(B)数据访问方案中的一个位置(如果您正在实现存储库) 数据访问策略中的一个挑战是同时提供灵活性和可重用功能。同时要有效率。在处理业务逻辑的同时,要做到既解耦又内聚。狡猾 存储库是一种旨在帮助实现所有这些平衡的模式。用于将db(或任何内容)转换为实体类或从实体类转换为db的代码位于每个实体的一个位置。“数据访问类”可能由存储库类以及实际处理sql工作的类组成。当然,您不应该在每个存储库类中执行所有sql操作 示例:您可以从使用低效但简单的反射来填充实体对象开始,在存储库类中几乎不做任何工作;稍后,您可以使其对大容量实体更有效,但这对系统的其他部分是完全隐藏的。然后,您将一些配置移动到XML,但系统的其他部分不知道这一变化
LINQtoSQL和实体框架实际上利用了存储库模式,因为存储库类返回的实际上是该实体的可访问性。业务类可以应用额外的标准,这些标准实际上可以应用于sql,同时仍然提供数据持久性的完整封装。这真的很酷。那么您看到DAL对象使用存储库对象了吗?i、 当你说发出查询时,我认为它会通过调用存储库来实现这一点。。。几乎就像存储库是数据库中存储过程的代理,除了查询在存储库中…@vdh_ant:不,DAL通常不知道域模型。存储库的实现(n