首页 > 解决方案 > 在 LINQ 中使用通用列

问题描述

我有一个基Entity类型,我将其用作多个实体类型的基类:Customer : EntityProduct : Entity等。其中每个都有一个以实体类型命名的现有 id 列:CustomerIdProductId等。因为它们都有不同的名称但功能相同,我决定使用一个未映射的通用 Id 列,这些列中的每一个都可以定义来引用该类型的“真实”Id 列:

public abstract class Entity<T> where T: Entity<T>
{
    [NotMapped]
    public abstract int Id { get; set; }
}

public class Customer : Entity<Customer>
{
    [JsonIgnore]
    public override int Id { get => CustomerId; set => CustomerId = value; }

    public int CustomerId { get; set; }
}

问题是,当我尝试使用它时:

[HttpPut("put")]
public async Task<ActionResult<bool>>> PutEntity(List<T> entities)
{
    foreach (T entity in entities)
        if (!MyEntities.Any(e => e.Id == entity.Id))
            return NotFound(false);
}

我得到一个例外The LINQ expression 'DbSet<Customer>.Any(d => d.Id == ___Id_0' could not be translated.

有什么办法可以解决这个问题,以允许 LINQ 使用对具有未知名称的列的通用引用来运行查询?

标签: c#entity-frameworklinq

解决方案


尝试指定用于覆盖Id属性的列名:

public class Customer : Entity<Customer>
{
    [Column("CustomerId")]
    public override int Id { get; set; }

另一种解决方案是使用配置类。您还可以创建这些配置类的继承层次结构,以便在单个位置配置基本实体属性,同时您可以选择覆盖您认为合适的配置值。快速示例:

public abstract class BaseEntity
{
    public int Id { get; set; }
}

public class Customer : BaseEntity
{
    // Id not needed
}

public abstract class BaseEntityConfiguration<TEntity> 
    : IEntityTypeConfiguration<TEntity>
    where TEntity is BaseEntity
{
    public void Configure(EntityTypeBuilder<TEntity> builder)
    {
        builder.HasKey(c => c.Id); // defined in single location                
    }
}

public class CustomerConfiguration : BaseEntityConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        base.Configure(builder); // configure base class' properties

        builder
            .Property(c => c.Id)
            .HasColumnName("CustomerId"); // override column name
    }
}

推荐阅读