【问题标题】:EF Core list of EnumsEF Core 枚举列表
【发布时间】:2020-12-16 17:57:39
【问题描述】:

我正在开发一个在 Entity Framework Core 中组织酒店预订的小型应用程序。我需要添加有关每个房间的床位数量和类型的信息。我在想,我决定枚举列表会比将它存储在单独的表中更好。但我不知道如何实现它

public enum Bed
{
    Single = 1,
    Double = 2,
}

public class Room : IEntity
{
   [Key]
   public int Id { get; set; }
        
   public string RoomIdentifier { get; set; }
   public ICollection<Bed> Beds { get; set; }
        
   public int Floor { get; set; }
   public double Price { get; set; }

   public bool IsFree { get; set; }
   public bool IsOutOfService { get; set; }
   public bool ShouldBeCleaned { get; set; }
        
   public ICollection<RoomReservation> RoomReservations { get; set; }
}

有可能吗?我还想将其保存为 (1,2,1,2) 之类的字符串,然后对其进行解析以接收房间内床的数量和类型。非常感谢您的帮助!

【问题讨论】:

  • 默认情况下,枚举列表将存储在单独的表中。所以一串 Id 被解析回列表将是一个自定义序列化程序
  • 枚举作为整数存储在数据库中。值转换器用于在枚举类型与其等效数字之间进行转换。见docs.microsoft.com/en-us/ef/core/modeling/value-conversions
  • @RobertHarvey 如果我有一个枚举值就足够了,但就我而言,我有一个每个房间对象的枚举列表,我不知道这是否可行。
  • 我看不出枚举列表与任何其他对象的列表有何不同。
  • 通过不使用单独的表,您只会遇到问题 - 非标准更改检测,无法对此类“列”执行服务器端查询条件等。以逗号分隔的字符串存储值并不比存储日期更好/数字字符串而不是本机数据类型。现在数据库表(尤其是当通过 ORM 代码迁移管理时)是免费的(基本上没有成本),只需使用它们,不要浪费你的时间。我很确定几天后您将发送的下一个问题将是“如何使用 LINQ 和 EF Core 查找具有特定床位数和类型的房间”,但没有好的答案

标签: c# .net-core entity-framework-core blazor


【解决方案1】:

这是一个组成对象名称的示例,希望对您有所帮助。

在 OnModelCreating 中:

modelBuilder.Entity<Room>()
        .Property(e => e.BedList)
        .HasConversion(
            v => string.Join(',', v),
            v => v.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<Bed>())
        .Metadata.SetValueComparer(valueComparer);

您必须在下面创建自己的 valuecomparer 示例 列表:

var valueComparer = new ValueComparer<ICollection<string>>(
                    (c1, c2) => c1.SequenceEqual(c2),
                    c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
                    c => (ICollection<string>)c.ToHashSet());

【讨论】:

  • 为什么我需要ValueComparer?没有一个在这里工作正常。
  • @RogerioSchmitt 更改跟踪可能会识别列更改并在不需要值比较器的情况下进行写入。但老实说,我没有测试过。
【解决方案2】:

我误读了这个问题...如果您尝试将逗号分隔的列表存储在单个字段中,请按照 Richard 的示例...或者如果您有映射逻辑,请在映射逻辑中手动处理它。

以下答案仅适用于您尝试使用枚举而不是使用表格时,而不是如果您尝试将多个枚举值放入单个列中。


Ardalis Steve Smith 有一个不错的 C# 包,名为 SmartEnum。 GitHub Link

它将允许您拥有一个强类型枚举,但您可以将它作为字符串或整数保存在数据库中,或者随意。

这是一个例子:

public sealed class Bed : SmartEnum<TestEnum>
{
    // static instances of the SmartEnum Bed represents the enumerations
    public static readonly Bed Single = new Bed(name: "Single", value: 1, isPremium: false);
    public static readonly Bed Double = new Bed(name: "Double", value: 2, isPremium: true);


    // example additional property of each enumeration
    public bool IsPremium = false;


    private Bed(string name, int value, bool isPremium) : base(name, value)
    {
        IsPremium = isPremium;
    }
}

在上面的示例中,枚举由 int 值支持。您可以使用: SmartEnum&lt;TestEnum, string&gt; 将其由字符串支持。它支持隐式转换等,与 EF 配合得很好,并且您可以根据需要“列出”枚举。

【讨论】:

  • 嗯。 Dapper 不需要这些;您只需在 DTO 中将您的属性声明为枚举类型,Dapper 就会自动执行正确的操作(数据库字段是 int)。
  • @RobertHarvey 哦,当然,这是另一种选择——而是在域层处理问题。
  • 是的,我认为最好将这些值存储为字符串值,但也非常感谢其他建议
  • EF Core 也会自动执行此操作,并支持在数据库中将枚举值存储(和查询)为 int 或字符串,因此不需要额外的包。
  • @IvanStoev 我知道,就像我之前说的......这是解决领域层的问题,它有它的优势。
猜你喜欢
  • 1970-01-01
  • 2020-04-08
  • 2023-02-03
  • 2018-05-23
  • 2021-12-07
  • 2023-02-04
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多