实体框架的DbEntityEntry有一个方法 Collection ,它接受lambda表达式来加载实体。
DbCollectionEntry<TEntity, TElement> Collection<TElement>(Expression<Func<TEntity, ICollection<TElement>>> navigationProperty) where TElement : class;
在我的项目中,我们遵循存储库模式,所以为了调用它,我在存储库中创建了一个接受与参数相同的方法。
TModel GetItem<TElement>(object[] id, Expression<Func<TModel, object>> navigationProperty = null,
Expression<Func<TModel, ICollection<TElement>>> navigationCollection = null, string collectionEntity = "")
where TElement : class;
从业务逻辑层我将该方法调用为
var model = _repository.GetItem(
new object[]
{
viewModel.Id
},
navigationCollection: x => x.ProductSubVersions,
collectionEntity: nameof(ProductStatusSubSystem.SubSystem));
其中x是为BusinessManager和存储库定义的模型
public class ProductStatus : BaseModel
{
public ProductStatus()
{
// ReSharper disable once DoNotCallOverridableMethodsInConstructor
ProductSubVersions = new List<ProductStatusSubSystem>();
}
/// <summary>
/// Name of the product
/// </summary>
[Required, MaxLength(100)]
public string Name { get; set; }
/// <summary>
/// product version validity start date
/// </summary>
public DateTime ValidFrom { get; set; }
/// <summary>
/// product version valid till
/// </summary>
public DateTime? ValidTill { get; set; }
/// <summary>
/// This field used to keep track of history of a product
/// </summary>
public int ProductNumber { get; set; }
public bool DefaultProduct { get; set; }
/// <summary>
/// all versions of this product
/// </summary>
public virtual List<ProductStatusSubSystem> ProductSubVersions { get; set; }
/// <summary>
/// all fallback languages attached to this language
/// </summary>
public virtual List<ProductStatusLanguage> ProductStatusLanguages { get; set; }
}
业务经理
public class BaseBusinessManager<ProductStatus, ProductStatusViewModel>, IProductStatusBusinessManager
{
}
public class VersionBaseBusinessManager<TModel, TViewModel> : IVersionBaseBusinessManager<TModel, TViewModel>
where TModel : class, new()
where TViewModel : class, new()
{
private readonly ICrudRepository<TModel> _repository;
}
但现在我有一个奇怪的要求,我需要从实体加载一个以上的集合属性(我也想加载ProductStatusLanguages)。如何使用多种类型的TElement定义表达式&lt; Func&lt; TEntity,ICollection&lt; TElement&gt;&gt;&gt; 的列表?
这是存储库方法
public virtual TModel GetItem<TElement>(object[] id, Expression<Func<TModel, object>> navigationProperty = null, Expression<Func<TModel, ICollection<TElement>>> navigationCollection = null, string collectionEntity = "")
where TElement : class
{
var entity = Table.Find(id);
if (navigationProperty != null)
{
DatabaseContext.Entry(entity).Reference(navigationProperty).Load();
}
if (navigationCollection != null)
{
DatabaseContext.Entry(entity).Collection(navigationCollection).Load();
if (!string.IsNullOrWhiteSpace(collectionEntity))
{
DatabaseContext.Entry(entity)
.Collection(navigationCollection)
.Query()
.Include(collectionEntity).Load();
}
}
P.S:在阅读Ivan Stoev的评论后,我写了一个方法,它接受表达式作为参数并加载集合
public virtual void LoadCollection<TElement>(TModel entity,
Expression<Func<TModel, ICollection<TElement>>> navigationCollection, string collectionEntity = "") where TElement : class
{
if (entity == null)
return;
DatabaseContext.Entry(entity).Collection(navigationCollection).Load();
if (!string.IsNullOrWhiteSpace(collectionEntity))
{
DatabaseContext.Entry(entity)
.Collection(navigationCollection)
.Query()
.Include(collectionEntity).Load();
}
}