[英]EF Core get Navigation Properties of an entity from Model with multiplicity Zero or One
我正在創建一個通用類,以使用集成測試所需的實體來為數據庫添加種子。 我可以創建單個實體,但是當一個實體彼此依賴時,我必須手動指示班級首先創建父實體,然后繼續。 我試圖使這種檢測自動進行,從模型定義中獲取多重性為0或1的導航屬性列表(參考導航屬性),一旦完成,遞歸地我的類將首先調用自身以創建父實體(循環依賴)在此超出范圍)。
我曾經在.net Framework EF中執行此操作,但EF Core發生了很大變化。 我在EF Core中缺少的是RelationshipMultiplicity ,我在官方文檔中找不到任何對Multiplicity的引用,甚至棘手的解決方案是檢查導航屬性是否為集合,我想擁有更多控制權並保留所有東西簡單。
到目前為止,我正在使用以下方法探索模型定義:
var modelData = _context.Model.GetEntityTypes()
.Select(t => new
{
t.ClrType.Name,
DerivedNavigationProperties = t.FindDerivedNavigations(t.ClrType.Name),
DefiningNavigationProperties = t.FindDefiningNavigation(),
DeclaredForeignKeys = t.GetDeclaredForeignKeys(),
DeclaredNavigations = t.GetDeclaredNavigations(),
DerivedNavigations = t.GetDerivedNavigations(),
DerivedNavigationsInclusive = t.GetDerivedNavigationsInclusive(),
Navigations = t.GetNavigations() // This returns all Navigation Properties (INavigation)
});
在檢查了GitHub中的源代碼之后,我可以很有把握地說,EF Core中沒有諸如Multiplicity之類的東西。
我創建了一個枚舉,類似於使用的.net Framework 3.5+(請參閱: 官方文檔 ):
public enum RelationshipMultiplicity
{
Many = 2,
One = 1,
ZeroOrOne = 0
}
然后是擴展方法,該方法允許使用枚舉作為過濾器來獲取所有導航屬性。 我使用的關鍵是:
該方法允許按關系類型獲取所有Navigations屬性
public static class ModelExtensions
{
/// <summary>
/// Extension method used to get from the entity all navigation properties by multiplicity
/// </summary>
/// <typeparam name="T">Entity from where the navigation properties are taken</typeparam>
/// <param name="model">Context Model</param>
/// <param name="multiplicity">Type of multiplicity to use</param>
/// <returns>List of PropertyInfo of Navigation Properties</returns>
public static IEnumerable<PropertyInfo> GetNavigationProperties<T>(this IModel model, RelationshipMultiplicity multiplicity)
{
var navigations = model.GetEntityTypes().FirstOrDefault(m => m.ClrType == typeof(T))?.GetNavigations();
var properties = new List<PropertyInfo>();
switch (multiplicity)
{
case RelationshipMultiplicity.Many | RelationshipMultiplicity.ZeroOrOne:
return navigations?
.Select(nav => nav.PropertyInfo);
case RelationshipMultiplicity.Many:
return navigations?
.Where(nav => nav.IsCollection())
.Select(nav => nav.PropertyInfo);
case RelationshipMultiplicity.One:
return navigations?
.Where(nav => !nav.IsCollection() && nav.ForeignKey.IsRequired)
.Select(nav => nav.PropertyInfo);
case RelationshipMultiplicity.ZeroOrOne:
return navigations?
.Where(nav => !nav.IsCollection())
.Select(nav => nav.PropertyInfo);
default:
return null;
}
return properties;
}
}
用法示例:
var oneToManyRelations = _context.Model.GetNavigationProperties<Transaction>(
RelationshipMultiplicity.ZeroOrOne);
var manyToOneRelations = _context.Model.GetNavigationProperties<Transaction>(
RelationshipMultiplicity.Many);
var allRelations = _context.Model.GetNavigationProperties<Transaction>(
RelationshipMultiplicity.Many |
RelationshipMultiplicity.ZeroOrOne);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.