EF Core:忽略或打破引用属性命名约定而不重命名属性的方法

问题描述 投票:0回答:1

我正在尝试将 EF Core 与 MongoDB 结合使用,我已将附加信息分组到单独的类

MyInfo
ThirdpartyInfo

internal class MyObject
{
    [BsonId]
    public ObjectId Id { get; set; }

    public string Name { get; set; }

    public MyInfo? Info { get; set; }

    public ThirdpartyInfo? Thirdparty { get; set; }
}

internal class ThirdpartyInfo
{
    public int UserId { get; set; }
    public int MyObjectId { get; set; }
}

internal class MyInfo
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

class MyDbContext : DbContext 
{
    public DbSet<MyObject> Test { get; init; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
  
        modelBuilder.Entity<MyObject>().ToCollection("tests");
    }
}

使用

MyInfo
我没有问题,它可以完美保存并且不会生成警告。
ThridpartyInfo.MyObjectId
属性似乎与 EF Core 约定冲突,并在下面生成以下警告,但我无法重命名它。

警告:Microsoft.EntityFrameworkCore.Model.Validation[10625] 外键属性“ThirdpartyInfo.MyObjectId1”创建于 影子状态,因为属性与简单名称冲突 实体类型中存在“MyObjectId”,但要么未映射,要么 已用于其他关系,或与当前关系不兼容 关联的主键类型。请参阅https://aka.ms/efcore-relationships 有关 EF Core 中映射关系的信息。

有什么方法可以忽略

ThirdpartyInfo
类的任何约定吗?我试过了

modelBuilder.Ignore<ThirdpartyInfo>();

此后没有任何警告,但属性本身根本不会写回数据存储。警告没有问题,只是看起来不专业,而且我真的不希望在生产中看到它。

mongodb entity-framework-core
1个回答
0
投票

对于一对一关系,EF 将默认尝试通过各自的 PK 加入实体。例如:

internal class MyObject
{
    [BsonId, Key]
    public ObjectId Id { get; set; }

    public string Name { get; set; }

    public MyInfo? Info { get; set; }

    public ThirdpartyInfo? Thirdparty { get; set; }
}

internal class ThirdpartyInfo
{
    [BsonId, Key]
    public ObjectId MyObjectId { get; set; }
    public int UserId { get; set; }
}

每个PK的类型需要匹配。现在,如果 MyObjectId 不是 ThirdPartyInfo 的 PK,那么您需要显式配置关系以告诉 EF 哪个属性以及 FK 或主体密钥驻留在关系的哪一侧。

modelBuilder.Entity<MyObject>()
    .HasOne(x => x.Thirdparty)
    .WithOne()
    .HasForeignKey<ThirdPartyInfo>(x => x.MyObjectId);

但是请注意,在这种情况下,FK 类型仍然需要匹配。如果MyObject PK是这个ObjectId类型,那么ThirdPartyInfo中的FK需要匹配。这就是 EF 使用影子属性来解决问题的方法,它使用合适的类型创建了 MyObjectId1,因为 MyObjectId 无法胜任该任务。 (类型错误)

如果您需要使用 Int 作为 FK,那么您需要在 MyObject 端使用合适的 PrcipalKey:

internal class MyObject
{
    [BsonId, Key]
    public ObjectId Id { get; protected set; }

    public int MyObjectId { get; protected set; }

    // ...
}

modelBuilder.Entity<MyObject>()
    .HasOne(x => x.Thirdparty)
    .WithOne()
    .HasPrincipalKey<MyObject>(x => x.MyObjectId)
    .HasForeignKey<ThirdPartyInfo>(x => x.MyObjectId);
© www.soinside.com 2019 - 2024. All rights reserved.