C# 在不同实体框架DBContext中的两个实体之间创建数据库关系
我有两个对象(UserProfile和Login)驻留在不同的程序集中,我必须在SQLServer中创建它们之间的关系(我不关心DbContext关系,但我想确保它们各自表之间的数据库引用完整性) 最简单的方法是更新数据库(我首先使用代码)并运行alter表来创建关系,但是我认为这种方法有点脏(即使在Up方法中使用SqlResource) 我尝试使用HasOptional和Map方法创建此关系失败(当我尝试“HasOptional(a=>a.IdUsuario)…”之类的方法时,fluent api说ProfileId不是引用类型)C# 在不同实体框架DBContext中的两个实体之间创建数据库关系,c#,entity-framework,entity-framework-6,C#,Entity Framework,Entity Framework 6,我有两个对象(UserProfile和Login)驻留在不同的程序集中,我必须在SQLServer中创建它们之间的关系(我不关心DbContext关系,但我想确保它们各自表之间的数据库引用完整性) 最简单的方法是更新数据库(我首先使用代码)并运行alter表来创建关系,但是我认为这种方法有点脏(即使在Up方法中使用SqlResource) 我尝试使用HasOptional和Map方法创建此关系失败(当我尝试“HasOptional(a=>a.IdUsuario)…”之类的方法时,fluent a
//UserContext的类(程序集“A”)
公共类用户配置文件
{
公共int-Id{get;set;}//PK
//省略了一些属性
}
公共类UserContext:DbContext
{
DbSet UsersProfiles{get;set;}
}
//SecurityContext的类(程序集“B”)
公共类登录
{
公共int Id{get;set;}
公共字符串用户名{get;set;}
public int ProfileId{get;set;}//UserProfile的FK
}
公共类SecurityContext:DbContext
{
数据库集登录名{get;set;}
}
我尝试引用这两个类,包括导航属性,并使用“modelBuilder.Ignore”来选择我想要在每个上下文中真正同步的类,但这最终导致了循环引用问题
我收到消息“导航属性'UserProfile'不是'Login'类型上声明的属性。请验证它是否未从模型中明确排除,并且它是有效的导航属性。”如果只是为了映射目的而尝试创建假类,请执行以下操作
我遗漏了什么吗?是的,你遗漏了一些要点
UserProfile
是一个弱实体,它依赖于登录
。这种关系是1:1。1Login
具有1UserProfile
你的课程应该是这样的:
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);
modelBuilder.Entity<Login>()
.HasKey(i => i.UserProfileId);
modelBuilder.Entity<Login>()
.HasRequired(i => i.Profile)
.WithRequiredDependent();
编辑
由于Login
不属于域程序集,Login
是弱实体<代码>登录依赖于用户配置文件
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<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);
modelBuilder.Entity<Login>()
.HasKey(i => i.UserProfileId);
modelBuilder.Entity<Login>()
.HasRequired(i => i.Profile)
.WithRequiredDependent();
Fabio,您在某些方面是对的,但是您的解决方案有一个问题,因为正如我所解释的,我无法在UserProfile类中引用登录名(反之亦然),因为它们位于不同的程序集中,我将遇到循环引用问题,因此无法创建登录导航属性(UserProfile类位于域层,而登录位于横切/安全层)…谢谢。(Obrigado。)因此,在您的情况下,您只需执行相反的操作。登录是一个薄弱的实体。请看我编辑的回答。这样做现在我的DbContexts具有正确的关系,但包含登录的上下文在我尝试运行更新数据库时尝试重新创建UserProfile表(它已存在于数据库中)。我尝试使用键-IgnoreChanges创建迁移(添加迁移),但这也会使约束被忽略(这与我需要的正好相反)。我认为将两个上下文与现有实体/表混合使用不是一个好方法…尝试使用
modelBuilder.Ignore()
当您有很多实体时,将两个上下文混合到一个数据库中是一个很好的方法,对于DDD结构也是如此。查看这些链接此问题与问题无关,如果您找不到答案,您应该在另一个问题中询问
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);