EF Core In-Memmory Array mapping - PullRequest
       37

EF Core In-Memmory Array mapping

1 голос
/ 26 мая 2019

У меня есть столбец строкового массива в базе данных

ALTER TABLE sample ADD languages VARCHAR[] NULL;

который сопоставлен с моделью:

public string[] languages { get; set; }

Использование EF Core с PostgreSQL (Npgsql.EntityFrameworkCore.PostgreSQL 2.2.0) работает "из коробки".

Однако, когда я хочу проверить DbContext с помощью In-Memmory (Microsoft.EntityFrameworkCore.InMemory 2.2.4), я получил эту ошибку:

System.InvalidOperationException: не удалось отобразить свойство 'sample.languages', поскольку оно имеет тип 'string []', который не является поддерживаемым типом примитива или допустимым типом объекта. Либо явным образом сопоставьте это свойство, либо игнорируйте его, используя атрибут «[NotMapped]» или «EntityTypeBuilder.Ignore» в «OnModelCreating».

Итак, добавление этого в конфигурацию компоновщика модели решает ошибку In-Memmory:

 builder.Property(p => p.languages)
                    .HasConversion(
                        v => string.Join("'", v),
                        v => v.Split(',', StringSplitOptions.RemoveEmptyEntries));

Но поднимает новый (Npgsql):

Невозможно привести символ типа базы данных, изменяющийся [] к строке в Npgsql.NpgsqlDefaultDataReader.GetFieldValue [T] (столбец Int32)

У вас есть какие-нибудь подсказки, пожалуйста?

1 Ответ

2 голосов
/ 26 мая 2019

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

EF Core создает отдельную модель для каждого типа базы данных. Каждый поставщик баз данных предоставляет метод расширения DatabaseFacade, например IsSqlServer(), IsNpgsql(), IsInMemory() и т. Д., Который можно использовать внутри OnModelCreating для условной настройки различных сопоставлений для конкретного типа (типов) базы данных, если это необходимо.

Предполагаемое использование выглядит следующим образом:

modelBuilder.Entity<Sample>(builder =>
{
    if (!Database.IsNpgsql()) // <--
    {
         builder.Property(p => p.languages)
             .HasConversion(
                 v => string.Join("'", v),
                 v => v.Split(',', StringSplitOptions.RemoveEmptyEntries));    
    }
});

Если вы используете отдельные классы, реализующие IEntityTypeConfiguration<TEntity> для конфигурирования модели, то вы должны передать Database их конструктору и сохранить в члене класса, потому что EntityTypeBuilder<TEntity>, переданный методу Configure, не делает предоставить такую ​​информацию.

...