Как связать два навигационных свойства разных моделей с одним столбцом с внешним Id EFCore

Использую VS2022, EF Core 6, SQLite, Code First.

Представлен пример механизма хранения хода событий в большой системе.

Имеется следующие модели:


public class EntityBase
{
    public int CreateEventId { get; set; }
    public virtual Event CreateEvent { get; set; }
}

public class User : EntityBase
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Clip : EntityBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int EventId { get; set; }
    public virtual Event Event { get; set; }
    // другие свойства
}

public class Clip
{
    CreateUser = 10,
    ModifyUser = 11,
    DeleteUser = 12,

    CreateClip = 20,
    ModifyClip = 21,
    DeleteClip = 22,
}

public class Event 
{
    public int Id { get; set; }
    public EventType Type { get; set; }
    public EventTime { get; set; }
    public int UserId { get; set; }
    public virtual User User { get; set; }
    // интересующие свойства
    public int ObjectId { get; set; }
    public virtual User { get; set; }  // если EventType = 10..19 то не null 
    public virtual Clip { get; set; }  // если EventType = 20..29 то не null 
}

Свойство Event.ObjectId хранит Id на объект с которым произошло событие т.е. либо Clip.Id либо User.Id, для определения что за Id служит свойство Event.EventType.

Если способ как-то указать EF Core, что если в свойстве такие-то значения, то нужно связать с ObjectId такую-то модель.

  1. Рассматривал хранение в EF Core полиморфных моделей, но тогда User и Clip должны быть унаследованы от Event, что не допустимо.

  2. Можно отправить SQL свой скрипт, но если ли штатный способ в EF Core это реализовать?

  3. Знаю, что можно хранить в отдельных столбцах (вместо ObjectId хранить UserId и ClipId) и EF будет корректно все обрабатывать, но мне кажется, что это не лучший способ, так как есть возможность хранить оба Id, что семантически неверно.

Вот скрипт SQLite, который я использую для просмотра БД, отражающий то, что мне надо:

SELECT
    DATETIME(Events.EventTime,'localtime') AS 'LocalTime',
    (
        CASE
            WHEN Events.EventType = 10 THEN 'CreateUser'
            WHEN Events.EventType = 11 THEN 'ModifyUser'
            WHEN Events.EventType = 12 THEN 'DeleteUser'
            WHEN Events.EventType = 20 THEN 'CreateClip '
            WHEN Events.EventType = 21 THEN 'ModifyClip '
            WHEN Events.EventType = 21 THEN 'DeleteClip'
        END 
    ) AS "EventType",
    Events.ObjectId,
    (
        SELECT Users.Name FROM Users WHERE Events.EventType BETWEEN 10 AND 19 AND Users.Id = Events.ObjectId 
        UNION 
        SELECT Clips.Name FROM Clips WHERE Events.EventType BETWEEN 20AND 29 AND Clips.Id = Events.ObjectId
    ) AS 'Object',
    Events.EventData
FROM Events

Ответы (0 шт):