我是一个新手,对于实体框架(entity framework)很感兴趣,但在速度方面遇到了一些问题。我认为我可能没有正确使用懒加载(lazy loading),但是很难理解它的工作原理。我已经将我的数据模型层和业务实体层分开,并使用一个函数从我的数据模型中创建业务实体。在这个函数中,我遍历不同的嵌套实体来创建它们相应的模型。好了,够啰嗦的了,下面是一些代码:
IM_ITEM.cs (产品数据模型)
稍微提供一些信息..我使用数据库优先建模来创建我的数据模型,我正在测试的数据库没有大量数据。此外,我尝试在我的
我有什么做错了吗?或者像这样查询使用EF会很慢吗?
编辑:为了防止延迟加载,我更新了我的查询:
IM_ITEM.cs (产品数据模型)
public partial class IM_ITEM
{
public IM_ITEM()
{
this.IM_INV = new HashSet<IM_INV>();
this.IM_BARCOD = new HashSet<IM_BARCOD>();
this.IM_GRID_DIM_1 = new HashSet<IM_GRID_DIM_1>();
this.IM_GRID_DIM_2 = new HashSet<IM_GRID_DIM_2>();
this.IM_GRID_DIM_3 = new HashSet<IM_GRID_DIM_3>();
this.IM_PRC = new HashSet<IM_PRC>();
}
public string ITEM_NO { get; set; }
public string DESCR { get; set; }
// many more properties...
public virtual ICollection<IM_INV> IM_INV { get; set; }
public virtual ICollection<IM_BARCOD> IM_BARCOD { get; set; }
public virtual ICollection<IM_GRID_DIM_1> IM_GRID_DIM_1 { get; set; }
public virtual ICollection<IM_GRID_DIM_2> IM_GRID_DIM_2 { get; set; }
public virtual ICollection<IM_GRID_DIM_3> IM_GRID_DIM_3 { get; set; }
public virtual ICollection<IM_PRC> IM_PRC { get; set; }
}
企业实体创建方法:
public static ProductEntity FromEfObject(IM_ITEM obj) {
var product = new ProductEntity {
ItemNumber = obj.ITEM_NO,
StyleNumber = obj.VEND_ITEM_NO,
Title = obj.DESCR_UPR,
LongName = obj.ADDL_DESCR_1,
ShortDescription = obj.DESCR,
VendorCode = obj.ITEM_VEND_NO,
Quarter = obj.ATTR_COD_2,
Color = obj.PROF_ALPHA_2,
Markdown = obj.PRC_1,
Price = obj.REG_PRC ?? 0,
Status = obj.STAT,
DepartmentCode = obj.ATTR_COD_1,
DepartmentDigit = obj.ATTR_COD_1.Substring(0, 1),
MixAndMatch = obj.MIX_MATCH_COD,
Inventory = new Inventory(obj.IM_INV),
Sizes = new List<ProductSize>(),
Widths = new List<ProductSize>(),
Lengths = new List<ProductSize>(),
Barcodes = new Dictionary<string, string>()
};
if (obj.IM_PRC.Any()) {
var price = obj.IM_PRC.First();
product.DnsPrice2 = price.PRC_2.GetValueOrDefault();
product.DnsPrice3 = price.PRC_3.GetValueOrDefault();
}
foreach (var barcode in obj.IM_BARCOD) {
product.Barcodes.Add(barcode.DIM_1_UPR, barcode.BARCOD);
}
foreach (var size in obj.IM_GRID_DIM_1) {
product.Sizes.Add(ProductSize.FromEfObject(size));
}
foreach (var width in obj.IM_GRID_DIM_2) {
product.Widths.Add(ProductSize.FromEfObject(width));
}
foreach (var length in obj.IM_GRID_DIM_3) {
product.Lengths.Add(ProductSize.FromEfObject(length));
}
if (!product.Sizes.Any()) {
product.Sizes.Add(new ProductSize());
}
if (!product.Widths.Any()) {
product.Widths.Add(new ProductSize());
}
if (!product.Lengths.Any()) {
product.Lengths.Add(new ProductSize());
}
return product;
}
我用的方法来获取模型:
public ProductEntity GetProductById(string itemNumber, int storeNumber) {
var product = _unitOfWork
.GetProductRepository(storeNumber)
.GetQueryable()
.FirstOrDefault(p => p.ITEM_NO == itemNumber);
return product == null ? null : ProductEntity.FromEfObject(product);
}
GetQueryable方法:
internal DbSet<TEntity> DbSet;
public GenericRepository(TContext context)
{
Context = context;
DbSet = context.Set<TEntity>();
}
public virtual IQueryable<TEntity> GetQueryable()
{
IQueryable<TEntity> query = DbSet;
return query;
}
稍微提供一些信息..我使用数据库优先建模来创建我的数据模型,我正在测试的数据库没有大量数据。此外,我尝试在我的
GetProductById
方法中使用.Include()
来加载(我认为是急切地),但这甚至使它变得更慢了。我有什么做错了吗?或者像这样查询使用EF会很慢吗?
编辑:为了防止延迟加载,我更新了我的查询:
public ProductEntity GetProductById(string itemNumber, int storeNumber) {
var product = _unitOfWork
.GetProductRepository(storeNumber)
.GetQueryable()
.Include(p => p.IM_INV.Select(i => i.IM_INV_CELL))
.Include(p => p.IM_BARCOD)
.Include(p => p.IM_GRID_DIM_1)
.Include(p => p.IM_GRID_DIM_2)
.Include(p => p.IM_GRID_DIM_3)
.Include(p => p.IM_PRC)
.FirstOrDefault(p => p.ITEM_NO == itemNumber);
return product == null ? null : ProductEntity.FromEfObject(product);
}
在追踪过程中,这给我一个很长的、比使用惰性加载更耗时的恶意查询 http://pastebin.com/LT1vTETb
_unitOfWork.GetProductRepository(storeNumber).GetQueryable()
的实现方式是什么?如果这一部分有误,可能会导致 EF 在执行FirstOrDefault
前将整个产品表查询到内存中,从而使查询变慢。请注意不要改变原意。 - SynerCoderstoreNumber
是否会影响加载的DbContext,还是它只是查询的一部分?CQ,你实现的GetQueryable
是为通用仓储设计的,但产品仓库应该怎么样呢? - SynerCoder