【问题标题】:Create a database relationship between 2 entities in different Entity Framework DbContexts在不同的实体框架 DbContexts 中创建 2 个实体之间的数据库关系
【发布时间】:2015-09-18 21:19:25
【问题描述】:

我有两个对象(UserProfile 和 Login)驻留在不同的程序集中,我必须在 SQL Server 中创建它们之间的关系(我不关心 DbContext 关系,但我想确保数据库引用各自表之间的完整性)。

最简单的方法是更新数据库(我首先使用代码)并运行更改表来创建关系,但是我认为这种方法有点脏(即使在 Up 方法中使用 SqlResource)。

我尝试使用 HasOptional 和 Map 方法创建此关系但未成功(当我尝试“HasOptional(a => a.IdUsuario)...”之类的方法时,流利的 api 表示 ProfileId 不是引用类型)。

// UserContext's Classes (Assembly 'A')
public class UserProfile
{
    public int Id { get; set; } // PK
    // some properties omitted
}

public class UserContext : DbContext
{
    DbSet<UserProfile> UsersProfiles { get; set; }
}

// SecurityContext's Classes (Assembly 'B')
public class Login
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public int ProfileId { get; set; } // UserProfile's FK
}

public class SecurityContext : DbContext
{
    DbSet<Login> Logins { get; set; }
}

我尝试引用这两个类,包括导航属性并使用“modelBuilder.Ignore”来选择我想要在每个上下文中真正同步的类,但这会导致循环引用问题。

我收到消息“导航属性 'UserProfile' 不是在类型 'Login' 上声明的属性。验证它没有明确地从模型中排除并且它是一个有效的导航属性。”如果尝试创建假类只是为了映射目的。

我错过了什么吗?

【问题讨论】:

    标签: c# entity-framework entity-framework-6


    【解决方案1】:

    是的,您遗漏了一些要点。

    UserProfile 是一个弱实体,它是Login 的依赖项。关系是 1:1。 1 个Login 有1 个UserProfile

    你的课程应该是这样的:

    public class UserProfile
    {
        //UserProfile does not have its own Id,
        //Its Id is the LoginId, which is the primary key and a foreign key
        //It ensures the 1:1 relationship
        public int LoginId { get; set; } // PK and FK
        // some properties omitted
        public Login Login { get; set; }
    }
    
    public class Login
    {
        public int LoginId { get; set; }
        public string UserName { get; set; }
    
        //Login does not have UserProfile fk
        //because it is the Principal of the relationship
        public UserProfile Profile { get; set; }
    }
    

    映射:

    modelBuilder.Entity<UserProfile>()
        .HasKey(i => i.LoginId);
    
    modelBuilder.Entity<Login>()
        .HasKey(i => i.LoginId);
    
    modelBuilder.Entity<Login>()
        .HasRequired(i => i.Profile)
        .WithRequiredPrincipal(i => i.Login)
        .WillCascadeOnDelete(false);
    

    生成的迁移:

    CreateTable(
        "dbo.Logins",
        c => new
            {
                LoginId = c.Int(nullable: false, identity: true),
                UserName = c.String(),
            })
        .PrimaryKey(t => t.LoginId);
    
    CreateTable(
        "dbo.UserProfiles",
        c => new
            {
                LoginId = c.Int(nullable: false),
            })
        .PrimaryKey(t => t.LoginId)
        .ForeignKey("dbo.Logins", t => t.LoginId)
        .Index(t => t.LoginId);
    

    编辑

    由于Login 不属于域程序集,Login弱实体Login 具有 UserProfile 的依赖关系。

    public class UserProfile
    {
        public int UserProfileId { get; set; } // PK
        // some properties omitted
        // we don't have Login property here
    }
    
    public class Login
    {
        //login pk must be userprofile FK
        //so it ensures the 1:1 relationship
        public int UserProfileId { get; set; } //PK
    
        public string UserName { get; set; }
    
        public UserProfile Profile { get; set; }// UserProfile's FK
    }
    

    映射:

    modelBuilder.Entity<Login>()
        .HasKey(i => i.UserProfileId);
    
    modelBuilder.Entity<Login>()
        .HasRequired(i => i.Profile)
        .WithRequiredDependent();
    

    生成的迁移

    CreateTable(
        "dbo.UserProfiles",
        c => new
            {
                UserProfileId = c.Int(nullable: false, identity: true),
            })
        .PrimaryKey(t => t.UserProfileId);
    
    CreateTable(
        "dbo.Logins",
        c => new
            {
                UserProfileId = c.Int(nullable: false),
                UserName = c.String(),
            })
        .PrimaryKey(t => t.UserProfileId)
        .ForeignKey("dbo.UserProfiles", t => t.UserProfileId)
        .Index(t => t.UserProfileId);
    

    【讨论】:

    • Fabio,您在某些方面是对的,但您的解决方案有问题,因为正如我所解释的,我无法在 UserProfile 类中引用登录(反之亦然),因为它们在不同的程序集,我将遇到循环引用问题,因此我无法创建登录导航属性(UserProfile 类位于域层,而登录位于横切/安全层)。 .谢谢。 (奥布里加多。)
    • 所以,在你的情况下,你只需要做相反的事情。登录是弱实体。看看我编辑的答案
    • 这样做现在我的 DbContexts 具有正确的关系,但是当我尝试运行 Update-Database 时,包含登录名的上下文会尝试重新创建 UserProfile 表(它已经存在于数据库中)。我尝试使用键 -IgnoreChanges 创建迁移(添加迁移),但这也使得约束被忽略(这与我需要的正好相反)。我认为将两个上下文与现有实体/表混合不是一个好方法......
    • 尝试使用modelBuilder.Ignore&lt;UserProfile&gt;(); 当您有很多实体时,将两个上下文混合到一个数据库中是一种好方法,也适用于 DDD 结构。看看这些链接msdn.microsoft.com/en-us/magazine/jj883952.aspxstackoverflow.com/questions/11197754/…
    • 这个问题与问题无关,如果没有找到答案,请在另一个问题中提问
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    相关资源
    最近更新 更多