检查实体是否在Code First中有依赖项



在允许删除之前,我试图检查我的实体是否有任何依赖项:

通常我们可以对每个实体类型这样做:

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);
对于引用导航,只需执行nullcheck
dependenciesExist = property.GetValue(entity) != null 

和对于集合(都跳过多对多或常规一对多)执行IEnumerable<object>检查,如开头所示。

最新更新