感谢您的光临。
在我的.NET应用程序中,我通常具有一个包含我的业务方法的业务逻辑层(BLL)和一个包含我的Entitiy类以及用于处理原子实体的任何方法(即,单个实体的CRUD方法)的数据访问层(DAL)。这是一个非常典型的设计模式。
这是我的意思的伪代码示例:
BLL
public static int CreateProduct(ProductModel product){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price
});
}
从
public int CreateProduct(Product p){
var db = new MyDataContext();
db.Products.AddObject(p);
db.SaveChanges();
return p.Id;
}
这个简单的例子没有问题。
理想情况下,实例化数据上下文并使用该数据上下文的所有事务都存在于DAL中。但是,如果我尝试处理稍微复杂一些的对象,这将成为一个问题:
BLL
public static int CreateProduct(ProductModel product){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price,
ProductType = DAL.SomeClass.GetProductTypeById(product.ProductTypeId) //<--PROBLEM
});
}
现在,我没有保存实体,而是出现以下错误:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
好的,因此解决此问题的答案是将一个通用数据上下文传递给两个调用:
BLL
public static int CreateProduct(ProductModel product){
using{var db = new DAL.MyDataContext()){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price,
ProductType = DAL.SomeClass.GetProductTypeById(product.ProductTypeId, db) //<--CONTEXT
}, db); //<--CONTEXT
}
}
这解决了眼前的问题,但是现在我的参照透明性很差,因为我必须:
对于某些人来说,这可能不是问题,但对我而言,因为我以更加实用的风格编写代码,所以这是一个大问题。毕竟它们都是同一个数据库,那么为什么不管这些实体的数据上下文实例为何,我都无法处理它们呢?
我意识到有些人可能会想简单地说为所有调用创建一个公共数据上下文。这不会成功,因为出于多种原因这样做是不好的做法,最终会导致连接池溢出。有关更多详细信息,请参见此好答案。
任何建设性的意见表示赞赏。
我个人跟踪工作单元,并通过静态方法将数据上下文与其关联。如果您不是在谈论寿命长的操作,例如我当前的项目,一个ASP.NET应用程序,其中每个请求都是一个(主要是)不同的单元,并且请求的开始和结束与该单元的开始/结束是一致的,则此方法非常有用。我将数据上下文存储在请求CurrentContext中,如果您不熟悉它,则它基本上是由系统管理的字典,该字典分配可通过静态方法访问的特定于请求的存储。那里的工作已经为我完成,但是您可以找到许多实现自己的工作单元模式的示例。每个Web请求一个DbContext ...为什么?
对于许多人来说,另一个同样可行的答案是注射。用于此目的(注入数据上下文),它基本上模拟了您在问题末尾编写的代码,但使您免受不喜欢的“非功能性”内容的侵扰。
是的,您只访问一个数据库,但是如果仔细查看,您会发现数据库不是这里的约束。这是由高速缓存引起的,高速缓存旨在允许多个不同的并发数据副本。如果您不希望这样做,那么可以使用其他许多解决方案。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句