如何在不引入第二个属性的情况下将数据库中的字符串映射到模型中的枚举?

时间:2019-04-16 20:19:34

标签: entity-framework

我的数据库有一个这样的表:

- CatId INT PK
- Name VARCHAR(100)
- FavoriteToy VARCHAR(100)

我的代码如下:

Cat.cs

public int CatId { get; set; }
public string Name { get; set; }
public Toy FavoriteToy {get; set; }

StaticVariables.cs

public enum Toy { Box, Ball, StuffedAnimal }

在规范化的数据库中,我将使用数据库中的查找表来存储所有玩具,然后Cats表将仅存储ToyId。但是在这种情况下,即使将FavoriteToy存储为字符串也很容易,即使它是多余的。

问题是我不知道如何将数据库中的字符串转换为代码中的枚举,而又不创建第二个FavoriteToyString属性并使FavoriteToy只是返回返回的枚举的计算对象来自FavoriteToyString

我听说这可能在当前版本的实体框架中实现。真的吗?你能告诉我怎么做吗?

2 个答案:

答案 0 :(得分:0)

您可以使用DTO类和automapper来解决您的问题:)

答案 1 :(得分:0)

通常,是的,查找表引用是一个更好的选择,因为您的数据可以符合引用完整性。也就是说,没有猫记录您的Enum希望不包含的玩具。 (尽管您的Enum必须与Toys表保持同步。)您可以使用EF的一些技巧,将EF配置为将枚举存储为字符串:

public class Cat
{
  [Key]
  public int CatId { get; set; }
  public string Name { get; set; }

  [Column("FavoriteToy")]
  public string FavoriteToyMapped { get; set; }

  [NotMapped]
  public Toy FavoriteToy 
  {
    get { return (Toy)Enum.Parse(typeof(Toy), FavoriteToyMapped); }
    set { FavoriteToyMapped = value.ToString(); }
  }
}

此方法的警告是,您可能使用Linq到Entity过滤猫的最爱玩具时,您需要在查询表达式中引用FavoriteToyMapped值,因为EF / DB不知道什么是FavoriteToy。

即 带有“纱”的最爱玩具的猫

var catsThatLoveYarn = context.Cats.Where(c => c.FavoriteToyMapped == Toys.Yarn.ToString()).ToList();
// not
var catsThatLoveYarn = context.Cats.Where(c => c.FavoriteToy == Toys.Yarn).ToList();
// Will error because EF doesn't map that property.

使用实体实例后,该实体集已从数据库中撤回,您可以使用FavoriteToy进一步访问/优化查询。如果您过早使用该字段,并且EF尝试编写查询,请谨慎并为未知字段做好准备。

var threeYearOldCats = context.Cats.Where(c => c.Age == 3).ToList();
var threeYearOldCatsThatLoveYarn = threeYearOldCats.Where(c => c.FavoriteToy == Toys.Yarn).ToList();

这很好,因为第一个查询中的.ToList()执行了EF-to-SQL,所以threeYearOldCats现在是cat实体的本地List<Cat>,而不是IQueryable<Cat>