我是实体框架的新手,喜欢简单,但速度有些麻烦。我想我可能会错误地使用延迟加载,但很难绕过它。我已将数据模型层和业务实体层分开,并使用函数从我的数据模型中创建业务实体。在这个函数中,我迭代不同的嵌套实体来创建它们相应的模型。好吧,这里有足够的漫游代码:
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;
}
更多信息..我使用数据库优先建模来创建我的数据模型,而我正在测试的数据库没有大量数据。另外,我尝试在我的.Include()
方法中使用GetProductById
来加载(急切地相信)但是进一步放慢了速度。
我做了一些根本错误的事吗?或者使用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
答案 0 :(得分:1)
您可以优化查询以避免延迟加载。在这种情况下,当您从数据库加载对象时,您知道您必须将几乎整个对象图映射到内存。您无论如何都需要稍后查找所有这些外键 - 将所有内容作为一个查询更快,而不是让延迟加载完成工作。有关详细信息,请参阅here。
看起来应该是这样的:
public ProductEntity GetProductById(string itemNumber, int storeNumber) {
var product = _unitOfWork
.GetProductRepository(storeNumber)
.GetQueryable()
.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);
}
请注意,如果这些外键具有自己的外键(即IM_BARCOD具有IM_OtherType的集合),您还需要将其映射到ProductEntity模型,则还应包括这些外键。你可以这样做:
.Include(p => p.IM_BARCOD.Select(b => b.IM_OTHERTYPE))