簡體   English   中英

EF Core 外鍵:不兼容的類型

[英]EF Core Foreign Key: incompatible types

我查看了許多類似的問題,但沒有找到適用的解決方案。

我在測試期間收到以下錯誤消息:

System.InvalidOperationException:從 'Product.FeatureType' 到 'FeatureType.Product' 與外鍵屬性 {'Type': string} 的關系不能以主鍵 {'Id': Guid} 為目標,因為它不兼容。 為此關系配置一個主鍵或一組兼容的外鍵屬性。

外鍵應該是FeatureTypeType字段。

這只發生在我將Product.Type的類型設置為string而不是Guid時。 但它應該是一個string ,而不是一個Guid 我根本不明白這里有什么問題。 我以 DB-first 方法進行項目,使用此邏輯可以使用 SQL 毫無問題地創建數據庫。 我感謝每一個幫助。

編輯:這是我的 MSSQL model:

CREATE TABLE [Core].[FeatureType](
    [id] [uniqueidentifier] NOT NULL,
    [int_id] [int] IDENTITY(1,1) NOT NULL,
    [type] [varchar](50) NOT NULL UNIQUE,
    [description] [uniqueidentifier] NULL,
    [SysStartTime] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL,
    [SysEndTime] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL,
 CONSTRAINT [PK_FeatureType] PRIMARY KEY NONCLUSTERED
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
    PERIOD FOR SYSTEM_TIME ([SysStartTime], [SysEndTime])
) ON [PRIMARY]
WITH
(
SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [Core].[FeatureTypeHistory] )
)
GO

CREATE TABLE [Core].[Product](
        [id] [uniqueidentifier] NOT NULL, 
        [name] [varchar](100) NOT NULL UNIQUE, 
        [type] [varchar](50) NOT NULL FOREIGN KEY REFERENCES [Core].[FeatureType](type),
        [SysStartTime] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL,
        [SysEndTime] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL,
        CONSTRAINT [PK_Product] PRIMARY KEY NONCLUSTERED ([id] ASC)
        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
        ON [PRIMARY],
        PERIOD FOR SYSTEM_TIME ([SysStartTime], [SysEndTime])
    ) ON [PRIMARY] WITH (SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [Core].[ProductHistory] ))
GO

據我了解,這應該可行,因為FeatureType表的Type列是UNIQUE

表

我有以下型號:

public class Product : IDBModel
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Type { get; set; }

    public DateTime SysStartTime { get; set; }
    public DateTime SysEndTime { get; set; }

    public FeatureType FeatureType { get; }
}

public class FeatureType : IDBModel
{
    public Guid Id { get; set; }
    public string Type { get; set; }
    public Guid? Description { get; set; }

    public DateTime SysStartTime { get; set; }
    public DateTime SysEndTime { get; set; }

    public TxtID TxtIDDescription { get; set; }
    public ICollection<Feature> Feature { get; }

    public ICollection<Product> Product { get; }
 }

以及以下相關的上下文配置:

public virtual DbSet<Product> Product { get; set; }
public virtual DbSet<FeatureType> FeatureType { get; set; }
...

modelBuilder.Entity<Product>(entity =>
        {
            entity.ToTable("Product", CoreSchema)
                .HasKey(k => new { k.Id }) 
                .HasName("PK_Product");
            entity.Property(a => a.Id).HasColumnName("id");
            entity.Property(a => a.Name).HasColumnName("name").IsRequired();
            entity.Property(a => a.Type).HasColumnName("type").HasMaxLength(50).IsRequired().IsUnicode(false);
            entity.Property(e => e.SysStartTime).HasColumnName("SysStartTime").ValueGeneratedOnAddOrUpdate();
            entity.Property(e => e.SysEndTime).HasColumnName("SysEndTime").ValueGeneratedOnAddOrUpdate();
            entity.HasOne(p => p.FeatureType)
                .WithMany(d => d.Product)
                .HasForeignKey(p => p.Type)
                .OnDelete(DeleteBehavior.Restrict);
        });

modelBuilder.Entity<FeatureAttributeSet>(entity =>
        {
            entity.ToTable("FeatureAttributeSet", "Core")
                .HasKey(e => new { e.Id })
                .HasName("PK_FeatureAttributeSet");

            entity.Property(e => e.Id).HasColumnName("id").IsRequired();
            entity.Property(e => e.AttributeSetId).HasColumnName("as_id").IsRequired();
            entity.Property(e => e.FeatureId).HasColumnName("feature_id").IsRequired();

            entity.Property(e => e.SysStartTime).ValueGeneratedOnAddOrUpdate();
            entity.Property(e => e.SysEndTime).ValueGeneratedOnAddOrUpdate();

            entity.HasOne(d => d.AttributeSet)
                        .WithMany(p => p.FeatureAttributeSet)
                        .HasForeignKey(d => d.AttributeSetId)
                        .OnDelete(DeleteBehavior.Cascade)
                        .HasConstraintName("FK_FeatureAttributeSet_AttributeSet");
            entity.HasOne(d => d.Feature)
                        .WithMany(p => p.FeatureAttributeSet)
                        .HasForeignKey(d => d.FeatureId)
                        .OnDelete(DeleteBehavior.Restrict)
                        .HasConstraintName("FK_FeatureAttributeSet_Feature");
        });

解決方法是配置PrincipalKey。 PrincipalKey 將允許我們定義具有唯一限制的引用鍵,這將是關系的目的地。 所以你可以像這樣使用

 modelBuilder.Entity<Product>(entity =>
    {
            entity.ToTable("Product", CoreSchema)
                .HasKey(k => new { k.Id }) 
                .HasName("PK_Product");
            entity.Property(a => a.Id).HasColumnName("id");
            entity.Property(a => a.Name).HasColumnName("name").IsRequired();
            entity.Property(a => a.Type).HasColumnName("type").HasMaxLength(50).IsRequired().IsUnicode(false);
            entity.Property(e => e.SysStartTime).HasColumnName("SysStartTime").ValueGeneratedOnAddOrUpdate();
            entity.Property(e => e.SysEndTime).HasColumnName("SysEndTime").ValueGeneratedOnAddOrUpdate();
            entity.HasOne(p => p.FeatureType)
                .WithMany(d => d.Product)
                .HasPrincipalKey(p => p.Type)
                .HasForeignKey(p => p.Type)
                .OnDelete(DeleteBehavior.Restrict);
        });

您在 model 構建器語句中為.HasForeignKey(p => p.Type)中的 Product 的 FeatureType 指定的外鍵必須與 FeatureType 的主鍵類型相同。 因為 FeatureType 的 Id 屬性是一個 Guid,所以 Product 上的 Type 也必須是 Guid 類型才能用作與 FeatureType 關系的外鍵。

是否有不能將Type屬性的類型更改為 Guid 的原因?

您可以在 EF 中使用值轉換model 。

第一步是更改Product.Type的類型:

public class Product
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public DateTime SysStartTime { get; set; }
    public DateTime SysEndTime { get; set; }

    public Guid Type { get; set; } // <= Guid, not string
    public FeatureType FeatureType { get; }
}

這滿足了 EF 的要求,即主鍵和外鍵屬性應該具有相同的類型。

但僅此一項就會生成 SQL ,因為數據庫類型不同而引發異常。 這就是價值轉換有用的地方。 只需在OnModelCreating中添加一行:

entity.ToTable("Product")
    .HasKey(k => new { k.Id })
    .HasName("PK_Product");
// To convert string value from the database:
entity.Property(e => e.Type).HasConversion<string>();
...

現在 EF 接受關聯,並且還知道如何為查詢和插入生成正確的 SQL。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM