首页 > 解决方案 > Ef Core 2.2 和强类型 ID 属性上的外键

问题描述

我想one-to-many在两个实体之间建立关系。假设非常简单,我想在Blog对象上收集帖子,并Post带有博客的 id。

public class Blog
{
    public int Id { get; private set;}
    public virtual ICollection<Post> Posts { get; private set; }
    public Blog(BlogId id) {
        Id = id.Id;
    }
}

public class Post
{
    public int Id { get; private set;}
    public virtual BlogId BlogId { get; private set; }
}

public class BlogId: IComparable<int>
{
    public int Id { get; private set; }
    public BlogId(int id)
    {
       Id = id;
    }

    public static implicit operator int(BlogId id) => id.Id;
    public static implicit operator BlogId(int id) => new BlogId(id);
    public int CompareTo(int other) => Id.CompareTo(other);
}

配置:

public class BlogConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder.ToTable("Blogs");
        builder.HasKey("Id");
        builder.HasMany(n => n.Posts)
            .WithOne()
            .HasForeignKey(p => p.BlogId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);
    }
}

public class PostConfiguration : IEntityTypeConfiguration<Post>
{
    public void Configure(EntityTypeBuilder<Post> builder)
    {
        builder.ToTable("Posts");
        builder.HasKey("Id");
        builder.Property(p => p.BlogId)
            .HasConversion(v => v.Id, v => new BlogId(v));
    }
}

不幸的是,它不适用于强类型的 Id 对象。在这种情况下,我们得到一个异常:

从具有外键属性 {'BlogId' : BlogId} 的 'Post' 到 'Blog.Posts' 的关系不能以主键 {'Id' : int} 为目标,因为它不兼容。为此关系配置一个主键或一组兼容的外键属性。

我尝试使用隐式运算符、IComparable 接口、拥有的类型来解决它,但这些解决方案都不能在这里工作。作为关系创建过程的一部分,它只是忽略了 BlogId 类型的转换 ( builder.Property(p => p.BlogId).HasConversion(v => v.Id, v => new BlogId(v));)。

您知道这种情况的任何解决方法或标准解决方案吗?由于持久层的限制,我不想在域中进行更改。

标签: entity-frameworkef-core-2.1ef-core-2.2

解决方案


推荐阅读