Entity Framework с Fluent Mapping - составной первичный ключ, один ко многим - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть следующий код.Я хочу создать свободное отображение, чтобы мой образ имел необнуляемый составной первичный ключ, состоящий из Defect_Id и Asset_Id.Как мне этого добиться?Я получаю сообщение об ошибке Свойство «Дефект» нельзя использовать в качестве ключевого свойства для объекта «TSIR.Core.Domain.Image», поскольку тип свойства не является допустимым типом ключа.Поддерживаются только скалярные типы, строка и байт [].

public class Image
{
    public Defect Defect { get; set; }
    public int AssetId { get; set; }
}

public class Defect
{
    public int Id { get; set; }
    private ICollection<Image> _images;

    public ICollection<Image> Images
    {
        get => _images ?? (_images = new Collection<Image>());
        set => _images = value;
    }
}

public ImageConfiguration()
{
    ToTable("Images").HasKey(entity => new
    {
        Defect = entity.Defect,
        entity.AssetId
    });
}

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Я бы посоветовал больше придерживаться соглашения о коде структуры сущностей .Отклоняться от них можно только в том случае, если вам это действительно необходимо (и вы можете убедить своего руководителя проекта в том, что эти отклонения сделают ваши классы более понятными, лучше тестируемыми, лучше поддерживаемыми и т. Д.)добавить поля.Пусть структура сущностей решает, каким типом должны быть элементы "set".

Таким образом, очевидно, что каждый Defect имеет ноль или более Images, каждый Asset также имеет ноль или более Images, каждый Image принадлежит ровно одному Defect и одному Assert, а именно Defect и Asset с внешними ключами, которые Image имеет.

Если вы создали простые отношения «один ко многим»,тогда не было бы никаких проблем.

Defect Id 1
Asset Id 3

// Traditional one-to-many: allows several images with same [Defect, Assert]
Image Id 10 with DefectId 1 and AssetId 3
Image Id 11 with DefectId 1 and AssetId 3
Image Id 12 with DefectId 1 and AssetId 3

Проблема возникает, потому что вы хотите использовать эти внешние ключи в качестве первичных ключей.Это, вероятно, предотвращает два изображения с одинаковым [Дефект, Assert].

// your composite key allows only one image with this [Defect, Assert]
Image Id [1, 3] with DefectId 1 and AssetId 3
// no other Image for this Defect 1 and Asset 3 possible

Если и только если ваша модель представляет собой реальность, в которой невозможно иметь несколько изображений с одним и тем же [Дефект, Актив]только тогда ваше решение будет лучше.

class Defect
{
    public int Id {set; set;}
    ... // other properties

    // every Defect has zero or more Images
    public virtual ICollection<Image> Images {get; set;}
}
class Asset
{
    public int Id {set; set;}
    ... // other properties

    // every Asset has zero or more Images
    public virtual ICollection<Image> Images {get; set;}
}

class Image
{
    // composite primary key: [DefectId, AssetId]
    // every Image belongs to exactly one Defect, using foreign key
    public int DefectId {get; set;}
    public virtual Defect Defect {get; set;}

    // every Image belongs to exactly one Asset, using foreign key
    public int AssetId {get; set;}
    public virtual Asset Asset {get; set;}
}

В структуре сущностей столбцы ваших таблиц представлены не виртуальными свойствами, виртуальные свойства представляют отношения между вашими таблицами (однозначно- много-много-много, ...)

В вашем случае: не забывайте свои внешние ключи.

В OnModelCreating:

var imageEntity = modelBuilder.Entity<Image>();

// every image has composite primary key
imageEntity.HasKey(image => new {image.DefectId, image.AssetId});

Возможно, этого (вместе с вашими виртуальными свойствами) достаточно, чтобы структура сущностей обнаружила ваши отношения, особенно первичные ключи и внешние ключи.Если нет, сообщите об этом в структуру организации:

// every image belongs to exactly one Defect, using foreign key
imageEntity.HasRequired(image => image.Defect)
    .WithMany(defect => defect.Images)
    .HasForeignKey(image => image.DefectId,

imageEntity.HasRequired(image => image.Asset)
    .WithMany(asset => assert.Images)
    .HasForeignKey(image => image.AssetId);
0 голосов
/ 12 февраля 2019

По сути, вы не можете включить ваш объект Defect как часть ключа.

Включите в свой класс Image оба свойства int для AssetId и DefectId.Затем в вашей конфигурации используйте их вместо объекта Defect, который является причиной вашей ошибки.

public class Image
{
    public int DefectId { get; set; }
    public Defect Defect { get; set; }
    public int AssetId { get; set; }
}

public class Defect
{
    public int Id { get; set; }
    private ICollection<Image> _images;

    public ICollection<Image> Images
    {
        get => _images ?? (_images = new Collection<Image>());
        set => _images = value;
    }
}

public ImageConfiguration()
{
    ToTable("Images").HasKey(entity => new
    {
        entity.DefectId,
        entity.AssetId
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...