Entity Framework Intercept Generate Migration Script - PullRequest
0 голосов
/ 03 декабря 2018

Я использую Entity Framework 6.2 Code First (.net framework 4.6.1) и сопоставляю несколько сущностей для просмотра через атрибут таблицы.Это работает для операций выбора, и я обрабатываю Вставить / Обновить / Удалить с триггером записи для просмотра на стороне сервера SQL.Он работает, как и ожидалось, однако, когда я добавляю новую миграцию, Entity Framework генерирует сценарии RenameTable для используемого атрибута таблицы (фактически это ожидаемое поведение для EF).Но я хочу перехватить генерацию миграции и изменить эти сущности tableName на исходное имя.

мой код как;

[MapToView("Users","UsersView")]
public class User
{
...
}

Я написал атрибут MapToView, этот атрибут унаследован от TableAttribute и передан второму параметрук TableAttribute.Я создаю этот Атрибут, потому что, если я перехватываю генерацию миграции, возвращаю исходное имя таблицы с параметрами этого атрибута.

В этом случае, когда я запускаю «add -igrationigrationName», он создает сценарии миграции, подобные этому;

RenameTable(name: "dbo.Users", newName: "UsersView");

но я хочу создать пустую миграцию, когда я запускаю сценарий "add -igrationigrationName".

кто-нибудь может мне помочь?

1 Ответ

0 голосов
/ 04 декабря 2018

Я решаю проблему.Первое: проблема есть;Когда я сопоставляю сущность для просмотра кода EF, сначала создайте миграцию с помощью ViewName.Это проблема, потому что я хочу использовать View вместо таблицы.Поэтому я решаю проблему с помощью этих инструкций;

1 - Я создаю BaseEntityConfiguration, которая унаследована от EntityTypeConfiguration, и все классы конфигурации сущности наследуются.например:

public class UserConfig: BaseEntityConfiguration<User> //Generic Type is Entity
    {
        public UserConfig()
        {
        }
    }

2- Я создаю MapToViewAttribute, который унаследован от TableAttribute

public class MapToViewAttribute : TableAttribute
    {
        public string TableName { get; }
        public string ViewName { get; }

        public MapToViewAttribute(string tableName, string viewName) : base(viewName)
        {
            TableName = tableName;
            ViewName = viewName;
        }
    }

3 - Я использую MapToViewAttribute, например, User Entity для использования View.

 [MapToView("User","UserView")]
    public class User
    {
      ...
    }

И в конструкторе BaseEntityConfiguration я получаю общий тип и пользовательские атрибуты.Если какой-либо объект имеет атрибут MapToView, я передаю параметр TableName в метод ToTable.Поэтому во время выполнения EF использует View для этих объектов, но не создает миграцию с RenameTable для этих объектов.

protected BaseEntityConfiguration()
        {
            var baseType = typeof(TEntityType);
            var attributes = baseType.GetCustomAttributes(true);
            foreach (var attr in attributes)
            {
                if (attr.GetType() == typeof(MapToViewAttribute))
                {
                    var tableName = ((MapToViewAttribute)attr).TableName;
                    ToTable(tableName);
                }
            }
        }

Последний EF не использует ваши файлы конфигурации, поэтому вы должны указать EF использовать его вМетод InternalModelCreate класса DbContext.Моя реализация такова:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            var typesToRegister = Assembly.GetExecutingAssembly()
                .GetTypes().Where(IsConfigurationType);

            foreach (var type in typesToRegister)
            {
                dynamic configurationInstance = type.BaseType != null
                                                && type.BaseType.IsGenericType
                                                && type.BaseType.GetGenericTypeDefinition() == typeof(BaseEntityConfiguration<>)
                    ? Activator.CreateInstance(type, culture)
                    : Activator.CreateInstance(type);

                modelBuilder.Configurations.Add(configurationInstance);
            }

            modelBuilder.Types().Configure(t => t.ToTable(t.ClrType.Name));
            BaseDbContext.InternalModelCreate(modelBuilder);
        }

Но если вы используете этот подход, вы должны создать Вставить, Обновить и Удалить Триггеры / Правило (если вы используете триггер SQLServer, это вариант, но если вы используете правило postgresql, то это лучший вариант)потому что EF использует это представление для операций вставки, обновления и удаления.

...