在允许删除之前,我试图检查我的实体是否有任何依赖项:
通常我们可以对每个实体类型这样做:
public class Company{
public int id;
public string name;
public virtual IList<Department> Departments { get; set; }
public virtual IList<Building> Buildings {get;set;}
public bool hasDependencies => Departments.Any() || Buildings.Any();
}
但我想对实体可能具有的任何消极属性进行通用处理
注意:延迟加载是启用的
public bool HasDependencies()
{
int ExampleEntityId = 2; // just example
Company companyEntity = _unitofwork.CompanyRepository.GetEntityById(ExampleEntityId);
IEnumerable<PropertyInfo> propertyInfoList = _unitofwork.CompanyRepository.GetNavigationProperties();
bool dependenciesExist = false;
foreach (PropertyInfo property in propertyInfoList)
{
dependenciesExist = companyEntity.**property**.Any(); //This obviously doesn't work, but just to convey the intent.
if (dependenciesExist) {
break;
};
}
return dependenciesExist;
}
这是GetNavigationProperties方法:
public IEnumerable<PropertyInfo> GetNavigationProperties()
{
var modelData = _context.Model.GetEntityTypes(typeof(TEntity)).ToList()[0];
var propertyInfoData = modelData.GetNavigations().Select(x => x.PropertyInfo);
return propertyInfoData;
}
我查阅了包括以下内容在内的许多页面来弄清楚这个问题:
EF5如何获取域对象的导航属性列表
在Code First
中检查实体是否在其他实体中有引用如果你依赖于装载导航的实体实例(惰性的,急切的或显式的),你可以很容易地模拟Any
检查集合,因为它们都可以被强制转换为IEnumerable<object>
,例如
dependenciesExist = property.GetValue(entity) is IEnumerable<object> collection
&& collection.Any();
但是注意GetNavigations()
API不返回跳过导航(即EF Core 5.0通过隐式连接实体引入了多对多)-这些是由GetSkipNavigations()
API返回的。同时GetNavigations()
返回bot集合和引用导航,所以如果你需要过滤掉它们,或者单独处理它们,你最好返回EF Core元数据对象,而不是反射部分。例如
var entityType = _context.Model.FindEntityType(typeof(TEntity));
var collectionNavigations = entityType.GetNavigations()
.Where(nav => nav.IsCollection)
.Concat<INavigationBase>(entityType.GetSkipNavigations());
var referenceNavigations = entityType.GetNavigations()
.Where(nav => !nav.IsOnDependent);
对于引用导航,只需执行null
check
dependenciesExist = property.GetValue(entity) != null
和对于集合(都跳过多对多或常规一对多)执行IEnumerable<object>
检查,如开头所示。