Entity Framework - 基于外键关联的单向一对一关系

代码的世界,原以为世界关系很简单,确道是关系无处不在.NET世界里ORM框架中EntityFramework作为其中翘楚,大大解放了搬砖工作的重复工作,着实提高了不少生产力,而也碰到过不少问题!比如关系的映射!

一对一关系的映射:

用户账户密码信息表:包含用户名 密码 邮箱等账户登录时的信息

public class SystemAccount
    {
        public SystemAccount()
        {
            Id = DateUtils.GeneratedNewGuid();
        }
        public Guid Id { get; set; }
        public string Salt { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Tele { get; set; }
        public Guid UserId { get; set; }
        public virtual User User { get; set; }
        public virtual User CreateUser(string nick)
        {
            var user = new User();
            user.Nick = nick;
            return user;

        }
    }

  用户信息表:包含用户真实姓名,经纬度,昵称,性别等会员信息

public class User
    {
        public User()
        {
            Id = DateUtils.GeneratedNewGuid();
        }
        public Guid Id { get; set; }
        public string Nick { get; set; }
        public int Gender { get; set; }
        public Guid AccountId { get; set; }
        public virtual SystemAccount Account { get; set; }
    }

  然后fluent api关系配置如下

 public class SystemAccountMapping : FarmerEntityTypeConfiguration<SystemAccount>
    {
        public SystemAccountMapping()
        {
            this.HasKey(r => r.Id);
            this.Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
            this.HasRequired(r => r.User).WithMany().HasForeignKey(fk => fk.UserId);
        }
    }

  

 public class UserMapping : FarmerEntityTypeConfiguration<User>
    {
        public UserMapping()
        {

            this.HasKey(r => r.Id);
            this.Property(r => r.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
            this.HasRequired(r => r.Account).WithMany().HasForeignKey(fk => fk.AccountId);
        }
    }

  然后加上数据库初始化种子数据

internal sealed class CreateIfNoExistDatabase : DbMigrationsConfiguration<FarmerObjectContext>
    {
        public CreateIfNoExistDatabase()
        {
            AutomaticMigrationsEnabled = true;
            AutomaticMigrationDataLossAllowed = true;
        }

        protected override void Seed(FarmerObjectContext context)
        {
            SystemAccount account = new SystemAccount();
            account.UserName = "shatan776";
            account.Salt = "oxml";
            account.Password = StringUtils.GenerateSaltedHash("123456", StringUtils.CreateSalt(AppConstants.SaltSize));
            account.User = account.CreateUser("老子就是张三");
            context.Set<SystemAccount>().Add(account);
            context.SaveChanges();
        }
    }

  

满脸欢喜的debug,来上一口16年的雪碧,静静的等着,结果任务栏宇宙第一ide VisualStudio加蓝,

将 FOREIGN KEY 约束 ‘FK_dbo.Farmer_User_dbo.Farmer_SystemAccount_AccountId‘ 引入表 ‘Farmer_User‘ 可能会导致循环或多重级联路径。请指定 ON DELETE    NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
   无法创建约束。请参阅前面的错误消息。

多重循环引用,纳尼,

难道是SystemAccount中加载了User的导航,User中也有,重复了?于是乎,注释掉UserMapping中的导航配置

//this.HasRequired(r => r.Account).WithMany().HasForeignKey(fk => fk.AccountId);

  继续debug错误依据,于是乎又把导航Id注释掉

//public Guid AccountId { get; set; }

哒哒哒达,终于生成了数据库,种子数据也有插入

一对一的关系就这样生成了,执子之手,与子偕老,张三看上了李四。。。

琢磨着把以前的账户系统移过来,以前的主键是int类型的数据库自增的,修改相应类型后,报错了,找不到account_target,也对,当插入到数据库中时account主键Id是没有生成的,所以user是插入不进去的,笨办法,先插入account,然后再插入user,暂时解决了问题!

看了一下生成的数据库外键图

看数据库生成的关系,0=》1。。。可以送SystemAccount实体类中生成User,而User中生成SystemAccount就会报错,用户信息必须有会员账户记录,而会员账户记录可以没有用户信息

更多资料参考

Entity Framework - 理清关系 - 基于外键关联的单向一对一关系

时间: 2024-10-19 13:38:20

Entity Framework - 基于外键关联的单向一对一关系的相关文章

Hibernate,关系映射的多对一单向关联、多对一双向关联、一对一主键关联、一对一外键关联、多对多关系关联

2018-11-10  22:27:02开始写 下图内容ORM.Hibernate介绍.hibername.cfg.xml结构: 下图内容hibernate映射文件结构介绍 下图内容hibernate映射文件中主键自增规则.Hibernate实例状态(瞬时状态.持久化状态.托管状态).Hibernate初始化类获取session等方法 下图内容保存数据过程 下面内容保存数据顺序.查询数据方法 get().load()和延迟加载.删除数据 下图内容删除对象顺序.修改数据顺序 下面内容关联关系映射.

注解:【基于外键的】Hibernate单向1-&gt;1关联

Person与Address关联:单向1->1,[基于外键的] Person.java package org.crazyit.app.domain; import javax.persistence.CascadeType;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Generati

《Entity Framework 6 Recipes》中文翻译系列 (29) ------ 第五章 加载实体和导航属性之过滤预先加载的实体集合和修改外键关联

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-13  过滤预先加载的实体集合 问题 你想过滤预先加载的实体集合,另外,你想使用Code-First来管理数据访问 解决方案 实体框架不支持直接使用Include()时过滤关联实体集合,但我们可以通过创建一个匿名类型来完成同样的事情,匿名类型包含实体和要过滤的关联实体集合. 假设你有如图5-28所示的概念模型 图5-28 一个包含movies(电影)和它的categories(目录)的模

《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13  在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体,允许基类被实例化. 解决方案 假设你有如图6-20所示的模型. 图6-20 包含Invoice实体的模型 这个模型只包含一个单独的实体Invoice(发货单).我们想从Invoice派生一个新的实体,它表示删除掉的发货单.这将允许我们以更清晰的业务逻辑来分别对有效的发货单和已删除掉的发货进行不同的操作.按下面

hibernate 之 关联映射的基于外键的单向一对一映射

1. 人和身份证是一个一对一的关系,他们的表结构为: 2. 类结构:IdCard.java : public class IdCard { private String id; private String address; public IdCard() { } public IdCard(String id, String address) { super(); this.id = id; this.address = address; } public String getId() { r

hibernate 之 关联映射的基于外键的双向一对一关联

1. 人和身份证是一个一对一的关系,他们的表结构为: 2. 类结构:Person.java public class Person { private int id; private String name; private int age; private IdCard idCard; public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } pu

java之hibernate之基于外键的双向一对一关联映射

这篇讲解 基于外键的双向一对一关联映射 1.考察如下信息,人和身份证之间是一个一对一的关系.表的设计 2.类结构 Person.java public class Person implements Serializable{ private int id; private String name; private IdCard idCard; public Person() { } public Person(String name) { super(); this.name = name;

011一对一 唯一外键关联映射_单向(one-to-one)

²  两个对象之间是一对一的关系,如Person-IdCard(人—身份证号) ²  有两种策略可以实现一对一的关联映射 主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系:数据库表不会有额外的字段来维护它们之间的关系,仅通过表的主键来关联. 唯一外键关联:外键关联,本来是用于多对一的配置,但是如果加上唯一的限制之后,也可以用来表示一对一关联关系. 实例场景:人—-> 身份证号(PersonàIdCard),从IdCard看不到Person对象 对象模型实体类与一对一主键关联

Hibernate关系映射(二) 基于外键的双向一对一

基于外键的双向一对一关联映射 需要在一端添加<one-to-one>标签,用property-ref来指定反向属性引用. 还是通过刚才用户和地址来演示双向一对一关联. 代码演示 一.实体类 Account.cs,需要添加被控端的引用 package com.lxit.entity; import java.io.Serializable; public class Account implements Serializable{ public Account(){ } private int