EF Core получает навигационные свойства объекта из модели с кратностью ноль или единица. - PullRequest
0 голосов
/ 03 марта 2019

Я создаю универсальный класс для заполнения базы данных сущностями, необходимыми для интеграционных тестов.Я могу создавать отдельные объекты, но когда одно зависит от другого, я должен вручную дать указание своему классу сначала создать родительский объект, а затем продолжить.Я пытаюсь сделать это обнаружение автоматическим, получая из определения модели список свойств навигации с кратностью 0 или 1 (справочные свойства навигации), как только это будет сделано, рекурсивно мой класс будет вызывать себя для создания родительских объектов вначале (циклические зависимости).здесь находятся вне области видимости).

Раньше я делал это в EF для .net Framework, но 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)
    });

1 Ответ

0 голосов
/ 03 марта 2019

После проверки исходного кода в GitHub я могу с достаточной уверенностью сказать, что в EF Core нет такого понятия, как Multiplicity.

Я создал перечисление, подобное используемому .net Framework 3.5+ (см.: Официальная документация ):

public enum RelationshipMultiplicity
{
    Many = 2,
    One = 1,
    ZeroOrOne = 0
}

А затем метод расширения, который позволяет получить все свойства навигации, используя перечисление в качестве фильтра.Я использовал следующие ключевые вещи:

Метод позволяет получить все свойства навигации по типу отношения

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...