Как сопоставить столбец базы данных со свойством модели EF более эффективным способом, чем я делаю сейчас - PullRequest
0 голосов
/ 11 ноября 2018

У меня в SQL Server есть обнуляемый столбец varchar(max), который я сопоставляю с Guid? в EF-коде. Однако на самом деле это свойство находится в базовом классе, от которого происходят многие другие объекты.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Model1>().Property(e => e.Property1).HasConversion(p => p.ToString(), p => (Guid?)Guid.Parse(p));
}

Приведенная выше строка повторяется много раз для каждой таблицы. Есть ли способ сообщить EF, что это свойство базового класса, поэтому отображение может быть объявлено только один раз?

Ответы [ 3 ]

0 голосов
/ 11 ноября 2018

Лучше сделать следующее свойство расчета:

[Column("Property1")]
public string Property1Raw { get; set; }

[IgnoreDataMember]
public Guid? Property1
{
    get => Guid.TryParse(Property1AsString, out Guid result) ? result : (Guid?)null;
    set => Property1Raw = value?.ToString();
}
0 голосов
/ 11 ноября 2018

Другой способ сделать это - иметь соответствующий базовый класс IEntityTypeConfiguration:

internal class EntityConfiguration<T> : IEntityTypeConfiguration<T> where T : Entity
{
    public virtual void Configure(EntityTypeBuilder<T> builder)
    {
        builder.Property(e => e.Property1).HasConversion(p => p.ToString(), p => (Guid?)Guid.Parse(p));
        // ... Other base-specific config here
    }
}

(Предполагается, что здесь ваш базовый класс называется Entity - при необходимости измените).

Это работает лучше, когда вы используете шаблон разделения ваших сущностей, поэтому ваш может выглядеть так:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new Model1EntityConfiguration());
    modelBuilder.ApplyConfiguration(new Model2EntityConfiguration());
    // ...
}

...

internal sealed class Model1EntityConfiguration : EntityConfiguration<Model1>
{
    public override void Configure(EntityTypeBuilder<Model1> builder)
    {
        base.Configure(builder); // <-- here's the key bit
        // ...; e.g.
        builder.Property(c => c.Name).HasMaxLength(80).IsRequired();
    }
}
0 голосов
/ 11 ноября 2018

Конечно, это возможно. При отсутствии пользовательских соглашений это достигается с помощью «типичного» цикла modelBuilder.Model.GetEntityTypes(). Примерно так (просто измените базовый класс и имена свойств):

var entityTypes = modelBuilder.Model.GetEntityTypes()
    .Where(t => t.ClrType.IsSubclassOf(typeof(BaseClass)));

var valueConverter = new ValueConverter<Guid, string>(
    v => v.ToString(), v => (Guid?)Guid.Parse(v));

foreach (var entityType in entityTypes)
    entityType.FindProperty(nameof(BaseClass.Property1)).SetValueConverter(valueConverter);

Вы можете также рассмотреть возможность использования EF Core, поставляемого из коробки Guid в String конвертер:

var valueConverter = new GuidToStringConverter();
...