簡體   English   中英

EF查詢中的Linq神秘錯誤

[英]Linq mystery error in EF query

我有一個UserProfile類

 [Key]
    public int UserProfileId { get; set; }

    public string AppUserId { get; set; }

   ...code removed for brevity

    [Required]
    public NotificationMethod NotificationMethod { get; set; }

    public List<PrivateMessage> PrivateMessages { get; set; }

    public List<Machine> OwnedMachines { get; set; }

    public bool IsProfileComplete { get; set; }

    public byte[] Avatar { get; set; }
    public string AvatarUrl { get; set; }       

    public string GetFullName()
    {
        return $"{FirstName} {LastName}";
    }
}

我也有一個PrivateMessage類

 public class PrivateMessage
{
    [Key]
    public int Id { get; set; }

    public int MessageToUserId { get; set; }

    public int MessageFromUserId { get; set; }

    public DateTime DateSent { get; set; }
    public string Message { get; set; }
}

我設置了一個簡單的測試,以通過各種包含將用戶配置文件提取出來。 PrivateMessages總是錯誤。 這是一個錯誤的示例方法。

public static UserProfile GetUserProfileIncluding(string appUserId)
    {
        using (RestorationContext)
        {
            //RestorationContext.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

            return RestorationContext.MemberProfiles.Where(m => m.AppUserId == appUserId)
                  .Include(m=> m.PrivateMessages)
                  .FirstOrDefault();
        }
    }

指出的錯誤是

InnerException {“無效的列名稱'UserProfile_UserProfileId'。\\ r \\ n無效的列名稱'UserProfile_UserProfileId'。”} System.Exception {System.Data.SqlClient.SqlException}

我不明白,兩個表都沒有“ UserProfile_UserProfileId”列

如果我使用屬性OwnedMachines而不是PrivateMessages,它會很好地工作(不是真的,當有6個匹配項時,它僅提取4條記錄,但我以后可以找出來)。

public static UserProfile GetUserProfileIncluding(string appUserId)
    {
        using (RestorationContext)
        {

            return RestorationContext.MemberProfiles.Where(m => m.AppUserId == appUserId)
                  .Include(m=> m.OwnedMachines)
                  .FirstOrDefault();
        }
    }

您可以在下面看到,Machine的設置與PrivateMessage完全相同,盡管它具有兩個UserProfiles而不是一個

public class Machine
{
    [Key]
    public int MachineId { get; set; }

    public int OwnerProfileId { get; set; }

    public int SerialNumber { get; set; }

    public string YearofManufacture { get; set; }

    public string ModelName { get; set; }

    public Manufacturer Manufacturer { get; set; }      

    public DateTime DateAcquired { get; set; }
}

我現在花了很多時間在此上。 這與我在PrivateMessage中具有兩個UserProfile Id int屬性有關嗎? (MessageToUserId和MessageFromUserId)。 我最初將這些設置為具有UserProfile屬性的外鍵,就像這樣

    [ForeignKey("MessageToProfile")]
    public int MessageToUserId { get; set; }

    public UserProfile MessageToProfile { get; set; }

    [ForeignKey("MessageFromProfile")]
    public int MessageFromUserId { get; set; }

    public UserProfile MessageFromProfile { get; set; }

但是我刪除了他們,以為他們可能是錯誤的根源,但顯然不是。

更新:經過一堆的反復試驗后,很明顯,當前方法將始終出錯,因為該方法正在尋找不存在的可導航屬性。 由於我在PrivateMessage中具有兩個int屬性,因此當嘗試將它們包含在UserProfile對象中時,我需要先按MessageToUserId進行過濾,然后再將它們包括在內。 不確定如何過濾和包含。

使用這種方法應該有效;

public static UserProfile GetProfileForLoggedInUser(string appUserId)
    {

        using (RestorationContext)
        {
            RestorationContext.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

            var profile= RestorationContext.MemberProfiles.Include(m => m.OwnedMachines)
                                           .FirstOrDefault(m => m.AppUserId == appUserId);
            var pms = RestorationContext.PrivateMessages.Where(m => m.MessageToUserId == profile.UserProfileId).ToList();

            if (profile != null) profile.PrivateMessages = pms;

            return profile;
        }
    }

但是它給出了相同的無效列錯誤UserProfile_UserProfileID。

這是TSql

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[MessageToUserId] AS [MessageToUserId], 
[Extent1].[MessageFromUserId] AS [MessageFromUserId], 
[Extent1].[DateSent] AS [DateSent], 
[Extent1].[Message] AS [Message], 
[Extent1].[UserProfile_UserProfileId] AS [UserProfile_UserProfileId]
FROM [RestorationContext].[PrivateMessages] AS [Extent1]
WHERE [Extent1].[MessageToUserId] = @p__linq__0

由於這只是查詢PrivateMessage表,因此查找它的UserProfileId是什么,因此它與該表無關。 這是來自SSMS的表格屬性

該UserProfileID廢話來自哪里?

該UserProfileID廢話來自哪里?

因為Machine類只有一個UserProfile外鍵,所以您的Machine包含項起作用。

PrivateMessage類中,您有2個外鍵指向同一個表,因此,在UserProfile類中自然需要2個ICollection導航屬性。 EntityFramework不知道在PrivateMessage類中使用哪個外鍵來加載UserProfile類中的ICollection<PrivateMessage>屬性。

public ICollection<PrivateMessage> FromPrivateMessages { get; set; }
public ICollection<PrivateMessage> ToPrivateMessages { get; set; }

在您的上下文課程中

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<PrivateMessage>()
                .HasRequired(m => m.MessageFromProfile)
                .WithMany(t => t.FromPrivateMessages)
                .HasForeignKey(m => m.MessageFromUserId)
                .WillCascadeOnDelete(false);

    modelBuilder.Entity<PrivateMessage>()
                .HasRequired(m => m.MessageToProfile)
                .WithMany(t => t.ToPrivateMessages)
                .HasForeignKey(m => m.MessageToUserId)
                .WillCascadeOnDelete(false);
}

UPDATE

EF使用約定而不是配置,並且通過在PrivateMessage類中具有UserProfile導航屬性將暗示關系,並且EF會嘗試以<Navigation Property Name>_<Primary Key Name of Navigation Property type>的形式查找外鍵,這給你UserProfile_UserProfileId

您應該想知道為什么此時要使用UserProfile_UserProfileId而不是UserProfile_MessageToUserIdUserProfile_MessageFromUserId 那是因為您的外鍵屬性,告訴EF在UserProfile類中使用UserProfileId屬性。

您現在可以做的是,刪除像這樣的外鍵屬性

public int MessageToUserId { get; set; }

public UserProfile MessageToProfile { get; set; }

public int MessageFromUserId { get; set; }

public UserProfile MessageFromProfile {get; set; }

並添加另一個ICollection並按照我在更新前所述的方式進行modelBuilder配置。

暫無
暫無

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

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