Свойство типа класса Entity Framework для случая змеи - PullRequest
1 голос
/ 09 февраля 2020

Я хочу сопоставить Location типа RoomLocation с

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

Диаграмма базы данных

Database diagram

Примечание: в старом проекте я забыл добавить builder.HasKey, и это действительно сработало. Я посмотрел журналы, и Entity Framework теперь перевел запрос на user_, потому что я забыл, что именно произошло, я не могу повторить ситуация.

Я использую Entity Framework с Npgsql с SnakeCaseNamingConvention.

Ответы [ 2 ]

1 голос
/ 09 февраля 2020

Для получения инструкций по аналогичным вопросам в Entity Framework 6+ вы можете обратиться к этому ответу Это решение специально предназначено для EF-Core

вместо Complex Типы , как это предусмотрено в Entity Framework 6+, EF Core имеет концепцию собственные типы , это охватывает большинство случаев использования, которые поддерживаются Комплексные типы но допускает расширенное использование сценария ios, включая свойства и ключи навигации.

Хотя для этого в EF Core еще не реализована нотация атрибутов, вы можете легко использовать Fluent API для настройки собственного типа без каких-либо дальнейших изменений. для ваших классов:

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

    base.OnModelCreating(modelBuilder);
}

Это дополнительно обсуждается на SO здесь: Использование [ComplexType] в Entity Framework Core

1 голос
/ 09 февраля 2020

Следующее руководство предназначено для Entity Framework , , а не EF Core . Это все еще актуальное руководство для. Net реализаций Framework.


Функция EF, о которой вы здесь говорите, облегчается благодаря использованию Сложных типов .

  • Сложный тип не имеет ключей и поэтому не может существовать независимо.
  • Он может существовать только как свойства типов сущностей или других сложных типов.
  • Это не может участвовать в ассоциациях и не может содержать свойства навигации.
  • Свойства сложного типа не могут быть нулевыми.
  • Скалярные свойства сложных объектов могут быть нулевыми.

Отметив RoomLocation как сложный тип , EF не будет создавать или сопоставлять отдельную таблицу в базе данных, а вместо этого будет сопоставлять поля в таблице для типа, который содержит свойство для сложного типа. .

Это можно сделать с помощью Fluent API или Аннотации данных , однако, поскольку вы используете KeyAttribute, этот пример позволяет продолжить с Dat a Аннотации (иначе известные как Атрибут Обозначение)

Поэтому сделайте RoomLocation сложным типом:

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

Соглашение о присвоении имен по умолчанию для полей базы данных означает следующее для этой таблицы будет использовано отображение полей базы данных по умолчанию:

ПРИМЕЧАНИЕ: это MS SQL Синтаксис сервера, аналогичные типы будут использоваться в 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

Вы можете использовать соглашения или задавать c отображение через Fluent API для сопоставления этих полей с различными именованными полями.

ПРИМЕЧАНИЕ: Если регистр полей несколько отличается (Caml, нижний или верхний регистр), EF все равно разрешит это отображение и все равно будет работать против Postgres поля базы данных, которые все в нижнем регистре, как ваш пример

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