EF Core 2.1.0 устанавливает длину строки по умолчанию и тип столбца - PullRequest
0 голосов
/ 13 июня 2018

Так как Entity Framework использует nvarchar(max) по умолчанию для строк, я хотел бы установить что-то другое по умолчанию.

https://dba.stackexchange.com/questions/48408/ef-code-first-uses-nvarcharmax-for-all-strings-will-this-hurt-query-performan

В Entity Framework 6.1.3 я мог бы изменить OnModelCreating(DbModelBuilder modelBuilder) вот так:

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
modelBuilder.Properties<DateTime>().Configure(c => c.HasPrecision(0));

modelBuilder.Properties<string>()
    .Configure(s => s.HasMaxLength(256).HasColumnType("nvarchar"));

Если я затем изменил свойство с аннотациями данных, EF использовал эти значения вместо этого, например так:

[MaxLength(128)]
public string Name { get; set; }

[Column(TypeName = "nvarchar(MAX)")]
[MaxLength]
public string Comment { get; set; }

Однако, используя Microsoft.EntityFrameworkCore.SqlServer 2.1.0, я не могу сделать это какэто и я не могу использовать Conventions.

Я мог бы решить datetime таким образом, но если я попытаюсь сделать то же самое для строк, миграция скажет type: "nvarchar(256)", maxLength: 128, если я использую аннотации данных, например.Как я могу решить это?

foreach (var property in modelBuilder.Model.GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(DateTime)))
{
    property.Relational().ColumnType = "datetime2(0)";
}

1 Ответ

0 голосов
/ 14 июня 2018

Существует несколько атрибутов, косвенно влияющих на тип столбца свойства string - MaxLength (например, varchar(256) против varchar(MAX), IsUnicode (например, nvarchar против varchar) и IsFixedLength (например, char против varchar).

API текущей модели несовместим. Первый доступен через GetMaxLength и SetMaxLength, второй- через IsUnicode и IsUnicode, и нет общедоступного API модели для третьего (только свободный API).

Итак, чтобы установить MaxLength вы можете использовать:

foreach (var property in modelBuilder.Model.GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(string)))
{
    if (property.GetMaxLength() == null)
        property.SetMaxLength(256);
}

, что не совсем правильно, потому что null в этом случае имеет двойное значение - не указано и MAX.

. Для правильного использования требуетсяВнутренний API EF Core, который предоставляет гораздо больше методов конфигурации, в частности, позволяет передавать перечислимое значение ConfigurationSource вместе со значением атрибута. Значения enum * 1038 определяют приоритет конфигурации - с Convention будучи самым низким, то DataAnnotation и, наконец, Explicit самым высоким. Вся идея в том, что низшее первичноеКонфигурация Rity не перезаписывает конфигурацию, уже установленную с более высоким приоритетом.Все общедоступные API используют Explcit, в то время как в нашем случае Convention идеально подходит (поскольку мы имитируем обычные значения по умолчанию).

Так что, если вы принимаете предупреждение "Этот API поддерживает Entity FrameworkБазовая инфраструктура и не предназначена для использования непосредственно из вашего кода. Этот API может изменяться или удаляться в будущих выпусках. ", добавьте

using Microsoft.EntityFrameworkCore.Metadata.Internal;

и используйте

foreach (var property in modelBuilder.Model.GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(string)))
{
    property.AsProperty().Builder
        .HasMaxLength(256, ConfigurationSource.Convention);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...