Entity Framework Core 未绑定主键

问题描述 投票:0回答:1

我在 .NET Core 应用程序中使用 Entity Framework Core,但遇到了一些奇怪的问题。当我尝试检索以前保存的对象时,该对象的主键为空,即使它是在数据库中设置的。

示例/代码:

public class Context : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<UserData> UserDatas { get; set; }
    public DbSet<Session> Sessions { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        CreateRelationships(modelBuilder);
        CreateIndexs(modelBuilder);
    }

    private void CreateRelationships(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasOne(e => e.UserData)
            .WithOne(e => e.User)
            .HasForeignKey<UserData>(e => e.UserID)
            .IsRequired();

        modelBuilder.Entity<User>()
            .HasOne(e => e.Session)
            .WithOne(e => e.User)
            .HasForeignKey<Session>(e => e.UserID)
            .IsRequired();

        modelBuilder.Entity<User>()
            .Navigation(u => u.Session)
            .AutoInclude();

        modelBuilder.Entity<User>()
            .Navigation(u => u.UserData)
            .AutoInclude();
    }

    public bool GetUserByCondition(System.Linq.Expressions.Expression<Func<User, bool>> predicate, out User? user)
    {
        user = Users.FirstOrDefault(predicate);

        if (user == null)
        {
            return false;
        }

        Log.LogToDB($"UserData is null: {user.UserData == null}");
        Log.LogToDB($"Session is null: {user.Session == null}");
        Log.LogToDB($"User ID: {user.UserID}");

        // TODO: Figure out why eager loading isn't working
        Entry(user).Reference(u => u.Session).Load();
        Log.LogToDB($"Session ID: {user.Session.SessionID}");

        Entry(user).Reference(u => u.UserData).Load();
        Log.LogToDB($"UserData ID: {user.UserData.UserDataID}");

        // for some reason the context will think all of these are being added after updating them and calling .SaveChanges(). Manually attach them to fix this
        Attach(user);
        Attach(user.Session);

        // Exception throwing because user.UserData.UserDataID = 0 / is unset
        Attach(user.UserData);

        return true;
    }
}

public class User : IUser
{
     [Key]
     public long UserID { get; set; }
     public UserData UserData { get; set; }
     public Session Session { get; set; }

     protected User() { }

     public User(Context db)
     {
         UserData ud = new UserData(this);
         UserData = ud;
         db.UserDatas.Add(ud);
     }
}

public class Session : ISession
{
    [Key]
    public long SessionID { get; set; }
    public long UserID { get; set; }
    public User User { get; set; }

    protected Session() { }

    static public Session CreateSessionForUser(User user, out string token)
    {
       Session session = new Session()
       {
            UserID = user.UserID,
            User = user,
       };

       return session;
    }
}

static public class SessionHelper
{
     static public void CreateNewSessionForUser(Context db, User user)
     {
         Session newSession = Session.CreateSessionForUser(user, out token);

         db.Sessions.Add(newSession);
         db.SaveChanges();
     }
}

public class UserData : IUserData 
{
     [Key]
     public long UserDataID { get; set; }
     public long UserID { get; set; }
     public User User { get; set; }
}

奇怪的行为发生在

GetUserByCondition
。第一个日志检查是否
user.UserData == null
将打印
false
,但第二个日志检查
user.Session == null
将打印
true
,尽管两个导航都在
AutoInclude
中指定为
OnModelCreating

通过

手动加载
Session

Entry(user).Reference(u => u.Session).Load();

打印

user.Session.SessionID
将打印正确的id。但是,尝试对
UserData
执行相同的操作,将打印
null
0
,具体取决于我是否将
UserDataID
切换为可为空。我已确认所有 3 个对象都在数据库中,并且所有外键/关系均已设置。

enter image description here

enter image description here

enter image description here

任何有关 Entity Framework Core 无法检索

UserDatas
上的主键的帮助将不胜感激

c# asp.net-core entity-framework-core
1个回答
0
投票

我看到你改变了你的方法,但既然我找到了它,就会分享它!

首先,我发现你的 ctor 很奇怪,但经过一些调试后发现,当 EF Core 尝试从数据库加载你的对象时,它仅加载基于你的代码的

UserData
对象。这就是为什么您在数据库中看到您的对象但没有被 EF Core 加载!

public User(Context db)
     {
         UserData ud = new UserData(this);
         UserData = ud;
         db.UserDatas.Add(ud);
     }
© www.soinside.com 2019 - 2024. All rights reserved.