我正在处理的项目中有以下域模型,它们是
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public virtual User { get; set; }
}
public class User
{
public int Id { get; set; }
public string LoginName { get; set; }
public string Password { get; set; }
}
我基本上有一个Person
实体和一个User
实体,Person
可以在没有User
的情况下存在,但如果没有User
则Person
不能存在Person
1}}。我也只希望EF中的关系单向加载(即当我加载User
实体时我想要导航属性到User
但不是另一种方式)
我发现我必须在两个对象上创建关系属性来实现关系映射,当然不希望这个或者在一个方向上检查NULL的开销,我宁愿{{1}实体没有Person
属性。
任何人都可以帮助定义正确的模型和关系映射,以便在运行时生成正确的EF Code-First配置和对象模型,我尝试了以下内容:
modelBuilder.Entity<Person>()
.HasOptional(t => t.User)
.WithRequired(t => t.Person)
.Map(x => x.MapKey("PersonId"))
.WillCascadeOnDelete();
此操作正在加载具有Person
属性为NULL的User
实体
如果有人能提供帮助,我们将不胜感激
答案 0 :(得分:1)
您需要正确配置实体:
.WithRequired()
。one-to-one
关系时,key
属性的名称在两个实体中都必须相同。因此,您只需使用HasOptional(t => t.User).WithRequired();
即可实现所需目标。
为了完整起见,我在下面添加(或多或少)完整代码:
实体:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public virtual User User { get; set; }
}
public class User
{
public int Id { get; set; }
public string LoginName { get; set; }
public string Password { get; set; }
}
实体配置:
public class PersonConfig:EntityTypeConfiguration<Person>
{
public PersonConfig()
{
HasOptional(t => t.User).WithRequired().WillCascadeOnDelete();
}
}
数据库上下文
public class MyDbContext:DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new PersonConfig());
}
}
生成的初始迁移(使用add-migration
):
public override void Up()
{
CreateTable(
"dbo.People",
c => new
{
Id = c.Int(nullable: false, identity: true),
FirstName = c.String(),
Surname = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Users",
c => new
{
Id = c.Int(nullable: false),
LoginName = c.String(),
Password = c.String(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.People", t => t.Id, cascadeDelete: true)
.Index(t => t.Id);
}
种子配置:
protected override void Seed(EF.MyDbContext context)
{
var person1 = new Person {Id= 1, FirstName = "Andrew", Surname = "Peters" };
var person2 = new Person {Id= 2, FirstName = "Brice", Surname = "Lambson" };
var person3 = new Person {Id= 3, FirstName = "Rowan", Surname = "Miller" };
context.People.AddOrUpdate(p => p.Id, person1, person2, person3);
var user1 = new User { Id = 1, LoginName = "Andrew", Password = "Peters" };
var user3 = new User { Id = 3, LoginName = "Rowan", Password = "Miller" };
context.Users.AddOrUpdate(p => p.Id, user1, user3);
}
用法:
MyDbContext ctx = new MyDbContext();
ctx.People.ToList().ForEach(person =>
{
System.Console.WriteLine($"Id:{person.Id}, Name: {person.FirstName} {person.Surname}");
if (person.User != null)
{
System.Console.WriteLine($"Found user, Id:{person.User.Id}, " +
$"Login: {person.User.LoginName}, Password: {person.User.Password}");
}
});
/*
Output:
Id:1, Name: Andrew Peters
Found user, Id:1, Login: Andrew, Password: Peters
Id:2, Name: Brice Lambson
Id:3, Name: Rowan Miller
Found user, Id:3, Login: Rowan, Password: Miller
*/