簡體   English   中英

實體類型“ Uri”要求定義主鍵

[英]The entity type 'Uri' requires a primary key to be defined

我引用了一個通用模型,因此無法控制其中的屬性。 假設它看起來像這樣:

  public class Message
  {
      public Guid Id { get; set; }
      public string Sender { get; set; }
      public Uri Uri { get; set; }
  }

其中UriSystem.Uri

在我的上下文中,我然后重寫OnModelCreating來設置主鍵:

  public DbSet<Message> Messages { get; set; }

  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
      modelBuilder.Entity<Message>()
          .HasKey(i => i.Id);
  }

然后,我在數據庫初始化程序中運行Initialize

  public void Initialize()
  {
      _logger.Information("Ensuring database is created.");

      _messageContext.Database.Migrate();
  }

但是出現以下錯誤:

The entity type 'Uri' requires a primary key to be defined.

關於如何解決這個問題的任何提示?

編輯:

顯然,這是一個已知問題

實體只能包含兩種類型的屬性類型(EF可以使用):

  1. 映射到原始SQL類型的類型(字符串,整數,布爾值,...)。
  2. EF中定義的實體類型。

由於Uri不會映射到原始SQL類型,因此EF會嘗試像對待實體一樣對其進行處理。

實體存儲在單獨的表中。 要將實體存儲在表中,它需要一個唯一的ID。


有一些解決方法。 我建議的方法可以維護Uri但可以阻止EF嘗試使用它。

第1步-使Uri [NotMapped]

這樣就可以使EF 忽略 Uri屬性,因為它無法正確處理它。

[NotMapped]
public Uri Uri { get; set; }

步驟2-制作EF 應該代替Uri處理的字符串屬性。

字符串值是從(現在是隱藏的) Uri屬性派生的,但是EF沒有看到。 它僅看到可用的字符串屬性。

public String URL 
{
    get
    {
        return this.Uri.AbsoluteUri;
    }
    set
    {
        this.Uri = new Uri(value);
    }
 }

這應該可以解決問題。 在代碼中,您可以直接使用Uri屬性(就像您已經做過的一樣),但是您已經設置了實體,因此EF可以改為使用URL字符串屬性。
EF檢索實體並設置其屬性(包括URL字符串屬性)后,還將隱式創建Uri屬性,您可以繼續使用它。

對於EF Core 2.0及更早版本,@ Flater的答案是正確的。

對於EF Core 2.1,有更優雅,更通用的方法來解決此問題,而不用轉換代碼污染模型: Value Converters

在您的情況下:

public class UriConverter : ValueConverter<Uri, string>
{
    public static UriConverter Instance = new UriConverter();

    private UriConverter() : base(value => ToUriString(value), value => ToUri(value)) { }

    private static string ToUriString (Uri uri) => uri?.ToString();

    private static Uri ToUri(string url) => Uri.TryPrase(url, out Uri uri)?uri:null;
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Message>().Property(e => e.Uri)
        .HasConversion(UriConverter.Instance);
}

或者對於這個非常簡單的案例,沒有w助手類:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Message>().Property(e => e.Uri)
        .HasConversion(
            uri => uri?.ToString(),
            url => Uri.TryPrase(url, out Uri uri)?uri:null
        );
}

暫無
暫無

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

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