簡體   English   中英

EF Core從多重性為零或一的模型中獲取實體的導航屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM