Entity Framework class 键入 属性 到 snake case

Entity Framework class type property to snake case

我想将 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_ 因为我忘记了什么确实发生了我无法重做这种情况。

我正在使用 Entity Framework 和 Npgsql 以及 SnakeCaseNamingConvention。

The following guidance is for Entity Framework, not EF Core. It is still relevant guidance for .Net Framework implementations.


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

  • A ComplexType doesn't have keys and therefore cannot exist independently.
  • It can only exist as properties of entity types or other complex types.
  • It cannot participate in associations and cannot contain navigation properties.
  • Complex type properties cannot be null.
  • Scalar properties of complex objects can be null.

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

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

所以使 RoomLocation 成为复杂类型:

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

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

NOTE: this is MS SQL Server Syntax, similar types would be used in Postgres, the names of the fields here are important for this discussion.

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 使用约定或特定映射将这些字段映射到不同的命名字段。

NOTE: If the casing of your fields is slightly different (Caml, Lower or Upper case) EF will still resolve this mapping and should still work against Postgres database fields that are all lower case like your example

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

For guidance on similar issues in Entity Framework 6+ you can refer to this solution specifically targets EF-Core

不同于Entity Framework 6+中提供的复杂类型,EF Core具有Owned Types[=23=的概念],这涵盖了 复杂类型 支持的大多数用例,但允许扩展使用场景,包括导航属性和键。

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

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

    base.OnModelCreating(modelBuilder);
}

这将在此处进一步讨论:

似乎没有人专门介绍过这一点,但是 Entity Framework 流畅的配置构建器确实有一个选项来定义自定义 table 和 属性 映射。

如果我的数据库中有一个名为 notifications 的 table,它具有一些名为 notification_titledate_createddate_modified 的属性。然后,您可以按如下方式在 class 中映射您的属性...

您的模特

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");
      });
   }
}

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