我有一个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 {&#34;无效的列名称&#39; UserProfile_UserProfileId&#39;。\ r \ n无效的列名称&#39; UserProfile_UserProfileId&#39;。&#34;} System.Exception {System.Data.SqlClient .SqlException}
我不明白,这两个表都没有列&#34; UserProfile_UserProfileId&#34;
如果我使用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&amp; 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废话来自哪里?
答案 0 :(得分:2)
您的Machine
包含有效,因为Machine
类只有一个UserProfile
的外键。
在PrivateMessage
课程中,您有2个外键到同一个表格,当然,您的ICollection
课程中需要2个UserProfile
导航属性。 EntityFramework不知道您的PrivateMessage
课程中使用哪个外键来加载ICollection<PrivateMessage>
课程中的UserProfile
媒体资源。
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);
}
<强>更新强>
EF使用约定优于配置,并且UserProfile
类中PrivateMessage
的导航属性将暗示关系,EF将尝试以<Navigation Property Name>_<Primary Key Name of Navigation Property type>
的形式查找外键,它为您提供UserProfile_UserProfileId
。
您应该想知道为什么UserProfile_UserProfileId
而不是UserProfile_MessageToUserId
或UserProfile_MessageFromUserId
。这是因为你的外键属性,告诉EF使用UserProfileId
类中的UserProfile
属性。
您现在可以做的是,删除像这样的外键属性
public int MessageToUserId { get; set; }
public UserProfile MessageToProfile { get; set; }
public int MessageFromUserId { get; set; }
public UserProfile MessageFromProfile {get; set; }
并添加另一个ICollection
并执行模型构建器配置,就像我在更新之前所说的那样。