簡體   English   中英

找不到實體類型的屬性的支持字段,並且該屬性沒有 getter

[英]No backing field could be found for property of entity type and the property does not have a getter

我遇到了一個例外

System.InvalidOperationException: No backing field could be found for property 'ApartmentId' of entity type 'Address' and the property does not have a getter.

這是我的Apartment class:

public class Apartment
{
    public Apartment(Address address)
    {
        Address = address;
    }

    private Apartment()
    {
    }

    public int Id { get; private set; }
    public Address Address { get; private set; }
}

這是我的Address值 object class:

public class Address : IEquatable<Address>
{
    private Address()
    {
    }

    public Address(string streetNumber, string streetName, string city, string state, string zipCode)
    {
        StreetNumber = streetNumber;
        StreetName = streetName;
        City = city;
        State = state;
        ZipCode = zipCode;
    }

    public string StreetNumber { get; private set; }
    public string StreetName { get; private set; }
    public string City { get; private set; }
    public string State { get; private set; }
    public string ZipCode { get; private set; }

    public bool Equals(Address other)
    {
        if (ReferenceEquals(null, other))
        {
            return false;
        }

        if (ReferenceEquals(this, other))
        {
            return true;
        }

        return String.Equals(StreetNumber, other.StreetNumber, StringComparison.OrdinalIgnoreCase) &&
               String.Equals(StreetName, other.StreetName, StringComparison.OrdinalIgnoreCase) &&
               String.Equals(City, other.City, StringComparison.OrdinalIgnoreCase) &&
               String.Equals(State, other.State, StringComparison.OrdinalIgnoreCase) &&
               String.Equals(ZipCode, other.ZipCode, StringComparison.OrdinalIgnoreCase);
    }
}

在我的實體配置中,我使用builder.OwnsOne(a => a.Address); . 在我的存儲庫中,我進行了以下調用:

    public async Task<Apartment> GetByAddressAsync(Address address)
    {
        return await _context.Apartments.FirstOrDefaultAsync(a => a.Address.Equals(address));
    }

它會產生上述異常。 有任何想法嗎? 我不知道為什么它說我的Address值 object 中有一個“ApartmentId”。

異常消息當然是可笑的,與實際問題沒有共同之處,即表達式

a => a.Address.Equals(address)

它是IQueryable表達式樹的一部分,因此 EF Core 正在嘗試將其轉換為 SQL。

像封裝這樣的面向對象特性不能很好地與基於可見性和知識的表達式翻譯配合使用。 EF Core 不是反編譯器,它看不到Equals方法的實現。 他們通常對未知方法所做的是拋出運行時異常,要求您使用可翻譯構造或顯式切換到客戶端評估。

但是實體類型有特殊處理。 EF Core 試圖通過將其隱式轉換為 PK(主鍵)比較來支持相等比較( == 、'!= , Equals`)翻譯。

這就是您擁有的實體類型的問題。 請注意,擁有的實體類型仍然是實體類型,但像您的Address這樣的引用擁有的類型沒有自己的 PK,因此例外。

當然,他們所做的是一個錯誤,但即使他們“修復”它,修復也只是不同的運行時異常。

解決方案當然是不使用Equals方法,而是顯式的成員比較,例如

a => a.Address.StreetNumber.ToUpper() == address.StreetNumber.ToUpper()
    && a.Address.StreetName.ToUpper() == address.StreetName.ToUpper()
    && a.Address.City.ToUpper() == address.City.ToUpper()
    && a.Address.State.ToUpper() == address.State.ToUpper()
    && a.Address.ZipCode.ToUpper() == address.ZipCode.ToUpper()

請注意,字符串比較由數據庫控制,因此如果您需要強制執行不區分大小寫的比較,則需要顯式ToUpper()

現在我知道這是代碼重復並破壞了封裝,但這是獲得服務器端過濾的唯一方法(除非您使用諸如NeinLinq.EntityFrameworkCoreDelegateDecompiler等的Lambda 注入之類的第 3 方庫)。

因為讀取整個表格后的客戶端過濾就像

_context.Apartments.AsEnumerable().FirstOrDefault(a => a.Address.Equals(address))

將是性能殺手(並且是在 EF Core 3.0+ 中刪除隱式客戶端評估的原因),而不是缺少自然async支持(需要額外的 package,這反過來會導致 EF Core DbSet出現問題 - 請參閱轉換 EF從 2.2 到 3.0 的核心查詢 - 異步等待)。

暫無
暫無

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

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