【问题标题】:Entity Framework with Fluent Mapping - Composite Primary Key, One to many具有流畅映射的实体框架 - 复合主键,一对多
【发布时间】:2019-07-05 10:41:22
【问题描述】:

我有以下代码。我想构建一个流畅的映射,以便我的 Image 具有由 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
    });
}

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    我的建议是更多地使用entity framework code first conventions。仅在您确实需要时才偏离它们(并且可以让您的项目负责人相信,这些偏离使您的类更易于理解、更好地测试、更好地维护等)

    保持您的实体类简单 POCO,不要添加字段。让实体框架决定“集合”项应该是什么类型。

    所以显然每个Defect 有零个或多个Images,每个Asset 也有零个或多个Images,每个Image 恰好属于一个Defect 和一个Assert,即@ 987654329@ 和 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
    

    问题出现了,因为你想使用这些外键作为主键。这可能是为了防止两个图像具有相同的 [Defect, 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);
    

    【讨论】:

    • 是的,关键似乎在你的最后一段。我做了一个复合键。 ToTable("Images").HasKey(entity => new { entity.DefectId, entity.AssetId }) .HasRequired(image => image.Defect) .WithMany(g => g.Images) .HasForeignKey(s=> s .DefectId);
    【解决方案2】:

    基本上,您不能将 Defect 对象作为 Key 的一部分。

    在 Image 类中包含 AssetId 和 DefectId 的 int 属性。然后在你的配置中使用那些而不是导致你的错误的缺陷对象。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多