【问题标题】:Entity Framework class type property to snake case实体框架类类型属性到蛇案例
【发布时间】:2020-02-08 21:59:45
【问题描述】:

我想将RoomLocation 类型的Location 映射到

Floor -> location_floor,
Building -> location_building,
Room -> location_room

Room.cs

public class Room
{
    [Key]
    public Guid Id { get; set; }
    public string Title { get; set; }
    public RoomLocation Location { get; set; }

    public DateTime CreationDate { get; set; }
    public DateTime ModificationDate { get; set; }  
}

public class RoomLocation
{
    public int Floor { get; set; }
    public int Building { get; set; }
    public int Room { get; set; }
}

数据库图

注意:在一个较旧的项目中,我忘记添加builder.HasKey,它确实有效我查看了日志,Entity Framework 现在将查询转换为user_,因为我忘记了到底发生了什么我无法重做这种情况.

我正在使用带有 Npgsql 的实体框架和 SnakeCaseNamingConvention。

【问题讨论】:

标签: asp.net postgresql entity-framework-core npgsql


【解决方案1】:

以下指南适用于Entity Framework,不是EF Core。它仍然是 .Net Framework 实施的相关指南。


您在此处询问的 EF 功能是通过使用 Complex Types 来实现的。

  • ComplexType 没有键,因此不能独立存在。
  • 它只能作为实体类型或其他复杂类型的属性存在。
  • 它不能参与关联,也不能包含导航属性。
  • 复杂类型属性不能为空。
  • 复杂对象的标量属性可以为空。

通过将RoomLocation 标记为复杂类型,EF 不会创建或映射到数据库中的单独表,而是映射到表中包含属性的类型的字段对于复杂类型。

您可以使用Fluent API 或Data Annotations 执行此操作,但是,当您使用KeyAttribute 时,此示例让我们继续使用数据注释(也称为属性 表示法)

所以将RoomLocation 设为复杂类型:

[ComplexType]
public class RoomLocation
{
    public int Floor { get; set; }
    public int Building { get; set; }
    public int Room { get; set; }
}

数据库字段的默认命名约定意味着该表将使用以下默认数据库字段映射:

注意:这是 MS SQL Server 语法,类似的类型将在 Postgres 中使用,此处的字段名称对于本次讨论很重要。

Id UniqueIdentifier NOT NULL,
Title NVarChar(MAX),
Location_Floor INT NOT NULL,
Location_Building INT NOT NULL,
Location_Room INT NOT NULL,
CreationDate DateTime2 NOT NULL
ModificationDate DateTime2 NOT NULL

您可以通过 Fluent API 使用约定或特定映射将这些字段映射到不同的命名字段。

注意:如果您的字段大小写略有不同(Caml、小写或大写),EF 仍将解析此映射,并且仍应适用于 Postgres 数据库字段像你的例子一样都是小写的

item.Location.Floor -> location_floor,
item.Location.Building -> location_building,
item.Location.Room -> location_room

【讨论】:

  • 我试过了,我加了[ComplexType],还是不行,可能是因为我使用的是实体框架核心,我在网上搜索时没有看到实体框架核心提一下,只有ef 6
  • 对,你应该改用 entity-framework-core 标签……这可能是最重要的事情。
  • 你的答案是正确的,但不是我的问题,ef core 的解决方案是modelBuilder.Entity<Room>().OwnsOne(p => p.Location);,如果你更新你的答案,我会接受。
  • 我已经单独发布了一个,主要是因为该建议对非核心 EF 仍然有效
【解决方案2】:

似乎没有人专门介绍过这一点,但实体框架流式配置构建器确实有一个选项来定义自定义表和属性映射。

如果我的数据库中有一个名为notifications 的表,其中包含一些名为notification_title、date_created 和date_modified 的属性。然后,您可以将您的属性映射到您的类中,如下所示...

你的模型

public class Notification
{
   public DateTime DateCreated { get; set; }
   public DateTime DateModified { get; set; }
   public string NotificationTitle { get; set; }
}

流畅的配置

public class DataContext : DbContext
{
   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
      modelBuilder.Entity<Notification>(entity =>
      {
         entity.ToTable("notifications");
         entity.Property(p => p.NotificationTitle).HasColumnName("notification_title");
         entity.Property(p => p.DateCreated).HasColumnName("date_created");
         entity.Property(p => p.DateModified).HasColumnName("date_modified");
      });
   }
}

我希望这对某人有所帮助。 ;)

【讨论】:

    【解决方案3】:

    有关 Entity Framework 6+ 中类似问题的指导,您可以参考 this response 此解决方案专门针对 EF-Core

    EF Core 的概念是 Owned Types,而不是 Entity Framework 6+ 中提供的复杂类型,这涵盖了支持复杂类型,但允许扩展使用场景,包括导航属性和键。

    虽然 EF Core 中尚未为此实现属性表示法,但您可以轻松使用 Fluent API 配置拥有的类型,而无需对您的类进行任何进一步的更改:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Room>().OwnsOne<RoomLocation>(x => x.Location);
    
        base.OnModelCreating(modelBuilder);
    }
    

    这将在此处进一步讨论:Using [ComplexType] in Entity Framework Core

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多