1-1 设置

   //DataAnnotation 1-1 | 1-0 table
//SQLtable : member , columns : memberId, name
//SQL basic logic : 1个table的PK, 是另一个table的PK and FK , 这就是1-1和1-0的关系
[Table("member")]
public class Member
{
[Key]
public Int32 memberId { get; set; }
public string name { get; set; }
[Required]
/*
1-0,这里就不要Required
1-1关系最好是放Required啦,在insert的时候才不会出错,但是...
如果你写Required,那么你在做update的时候这个address不能是Null,也就是说一定要inner join出来先,不是很方便.
*/
public virtual Address address { get; set; }
}
//SQLtable : address , columns : memberId, postcode, country
[Table("address")]
public class Address
{
/*
关键就是这个关系连接, "member" 是 tableName
*/
[Key, ForeignKey("member")] //foreignKey 一定要写在这里,不可以写在 Member 哦
public Int32 addressId { get; set; } //这里取名addressId也行
public string postcode { get; set; }
public string country { get; set; }
public virtual Member member { get; set; }
}

注 : ForeignKey("member") 的member 是取至于 virtual Member "member" , 这2个要一直

基本的 CRUD

using (EFDB db = new EFDB())
{
/*insert*/
db.members.Add(new Member
{
name = "keatkeat",
address = new Address
{
postcode = "",
country = "malaysia"
}
});
db.SaveChanges(); /*select*/
var members = db.members.Include(m => m.address).ToList(); //要include才会一起出来哦 /*update*/
var member = db.members.Include(m => m.address).First().name = "xinyao123";
db.SaveChanges(); /*delete*/
db.members.Remove(db.members.Include(m => m.address).First()); //要include出来才能一次删除2个table的数据!
db.SaveChanges();
}

这里有一个要注意的 :

如果 A 和 B 是 1-1 关系, 而 B 是一抽象类 C,D 是B的派生类,那么当我们想要替换掉 C 时,我们并不能单纯的 a.b = new D()

我们也不可以先删除再添加

db.Bs.remove(a.b);

a.b = new D();

我们必须使用 transaction, SaveChanges 2 次,

transaction.open();

db.Bs.remove(a.b);

db.SaveChanges();

a.b = new D();

db.SaveChanges();

transaction.commit();

这样才可以!

更新 : 2016-11-07

EF 1-1 的条件是 primaryKey 必须是 foreignKey, 也就是说 2 个 table 的 Id 必须是一样的值, 如果无法做到这一点, 则 1-1 无法成立.

当 1-1 遇上继承 TPH, 以上的条件就无法实现了,

这种情况下,我们只能无奈的使用 1-n 来替代, 然后在 foreignkey 的 table 上加上 unique 限制来模拟 1-1 的效果. 用起来很别扭, 但是目前没有好的方式去支持..无奈.

1-n 设置

    //1-n
/*
基本上如果没有必要就不要写required了,这样比较方便在update单个table的时候.(insert的时候自己要控制好!)
*/
[Table("prod")]
public class Prod
{
[Key]
public int prodId { get; set; }
public string code { get; set; }
[InverseProperty("prod")] //因为有超过1个,所以我们要告诉entity,这对应哪一个
public virtual ICollection<Color> colors { get; set; } //有多个colors,用ICollection | List 也可以
[InverseProperty("prodx")]
public virtual ICollection<Color> color2s { get; set; }
} [Table("color")]
public class Color
{
[Key]
public int colorId { get; set; }
public string name { get; set; } [ForeignKey("prod")] //指定一个FK, "prod" 是attr属性名,不是sql的哦
public int prodId { get; set; }
   [ForeignKey("prodId")] //虽然写这里也是可以表达foreignKey 关系,但是最好不要这样!
public virtual Prod prod { get; set; } //有一个prod [ForeignKey("prodx")]
public int prodxId { get; set; }
public virtual Prod prodx { get; set; }
}
InverseProperty (如果有做,lastModifier,handler就会有了),2个表有超过1个 1-n 关系,就要表明清楚对应的是哪一个。
1-n 的 foreignKey 不可以是 0, 如果真的没有也只能放 Null, 而且sql 要是nullable , foreignKey 类型是 int?.
nullable 虽然不会影响sql对foreignKey关系的验证或者级联,但是对索引搜索不好,所以还个简单的方法就是主表default create 1 row for 这种没有的情况,那么foreignKey 就可以连接到这row id 了。

n-n 设置

n-n 我不鼓励用 DataAnnotation, 除非用 default的tableName,比如 category , prod  = prodcategories , columns = Prod_prodId , Category_categoryId (基本上debug几次就可以知道它的自动命名了)

如果是要自己取名字的话,比如 category_and_prod,那就麻烦多多了...

参考 : https://social.msdn.microsoft.com/Forums/en-US/9d7a4803-53c6-44be-823d-dce6e85bb497/ef-41-customize-codefirst-manytomany-table-using-attributes

    /*
2表的连接表
*/
[Table("prod_mm_category")]
public class ProdAndCategory
{ [Key]
public Int32 ProdAndCategoryId { get; set; }
[Key]
[Column(Order = )]
[ForeignKey("category")]
public int categoryId { get; set; }
[Key]
[Column(Order = )]
[ForeignKey("prod")]
public int prodId { get; set; }
public Category category { get; set; }
public Prod prod { get; set; }
}
[Table("category")]
public class Category
{
[Key]
public Int32 categoryId { get; set; }
public string name { get; set; }
/*
注意这里是 ProdAndCategory 哦
*/
public virtual ICollection<ProdAndCategory> prods { get; set; }
}
[Table("prod")]
public class Prod
{
[Key]
public Int32 prodId { get; set; }
public string code { get; set; }
public virtual ICollection<ProdAndCategory> categorys { get; set; }
}

insert 也超麻烦..

db.categorys.Add(new Category
{
name = "Man",
prods = new List<ProdAndCategory>
{
/*
这里很麻烦吧...
*/
new ProdAndCategory
{
prod = new Prod
{
code = "MK100",
}
},
new ProdAndCategory
{
prod = new Prod
{
code = "MK200",
}
},
}
});

所以可以考虑用 Fluent API 替代

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
/*
cateogry "HasMany" prod , prod "WithMany" category , mapping logic
*/
modelBuilder.Entity<Category>().HasMany<Prod>(c => c.prods).WithMany(p => p.categorys).Map(m =>
{
m.MapLeftKey("Category_categoryId"); //第3 table 的连接 columnName 可以自己顺便取
m.MapRightKey("prodId"); //第3 table 的连接 columnName
m.ToTable("prodcategories"); //第3 tableName
});
base.OnModelCreating(modelBuilder);
}

用 Fluent API 或是自动命名 insert 也简单了

db.categorys.Add(new Category
{
name = "Man",
prods = new List<Prod>
{
new Prod
{
code = "MK100",
},
new Prod
{
code = "MK200",
}
}
});
db.SaveChanges();

更新 : 2015-10-08

有一种关系叫 双向 1对1

参考 :

http://stackoverflow.com/questions/6276299/creating-bidirectional-one-one-relationship-in-entity-framework-4-1-code-first

http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first-part-5-one-to-one-foreign-key-associations

个人不推荐使用,最明显的缺点是如果要删除关系,必须同时修改2个表的外键.

可以考虑使用多对多来做替代,虽然这样也不是很理想啦 ( 有best way的话请告诉我哦! )

Entity Framework with MySQL 学习笔记一(关系整理版)的更多相关文章

  1. Entity Framework with MySQL 学习笔记一(关系)

    这一篇说说 EF Fluent API 和 DataAnnotations 参考 : http://msdn.microsoft.com/en-us/data/jj591617.aspx http:/ ...

  2. Entity Framework with MySQL 学习笔记一(安装)

    声明 :  数据库是Mysql,本人的程度只到会写sql语句(不会储蓄过程), c# 会基本的ADO.NET数据库访问,LINQ基础. 这篇只做个人学习|温习作用. 新手可以参考,也请高手指正错误, ...

  3. Entity Framework with MySQL 学习笔记一(查看EF和SQL请求日志)

    做数据库的一向来都会很注意请求的次数还有语句.这关系到很多性能的问题. 因此在使用EF的时候如果不了解原理很可能会搞出很糟糕的请求. 所以呢,在还没有搞懂EF前最基本的是你得"看得见&quo ...

  4. Entity Framework with MySQL 学习笔记一(乐观并发)

    在做项目时,通常我们对乐观并发有几种处理模式 1. 告诉用户此数据已被其他人捷足先登,更改了.你就算新一下重来吧. 2.直接把数据覆盖上去,我最大. 3.用被人的数据. 这里给出 code first ...

  5. Entity Framework with MySQL 学习笔记一(继承)

    基本上sql中要表示继承关系有3中方式. 分别是,1表继承(TPH),2表继承(TPC),3表继承(TPT) 1表 : Person id type name classroom office 1 s ...

  6. Entity Framework with MySQL 学习笔记一(insert,update,delete)

    先说说 insert 吧. 当EF执行insert时,如果我们传入的对象是有关联(1对多等)的话,它会执行多个语句 insert到多个表, 并且再select出来填充我们的属性(因为有些column默 ...

  7. Entity Framework with MySQL 学习笔记一(拦截)

    参考 : http://msdn.microsoft.com/en-us/data/dn469464.aspx EF 允许我们在发送SQL请求和返回数据时做一些拦截的动作 比如可以自定义写 log , ...

  8. Entity Framework with MySQL 学习笔记一(验证标签)

    直接上代码 [Table("single_table")] public class SingleTable { [Key] public Int32 id { get; set; ...

  9. Entity Framework with MySQL 学习笔记一(复杂类型 Complex Types)

    有时候我们希望在sql一个表里面的column, 一部分被分化成另一个class 典型的例子是 Address 直接看代码: [Table("member")] public cl ...

随机推荐

  1. UVA10557- XYZZY(spfa+设置次数上限)

    题意:有N个房间,刚开始你位于1号房间,有100的能量值,你要到达N号房间,每两个房间之间有单向门相连接,你到达某个房间可以加上该房间的能量值, 如果你在未到达N号房间之前能量值耗尽,则死亡,否则胜利 ...

  2. 获取机器本地的公网ip地址

    1. ipecho.net/plain

  3. Git Push 不用再次输入用户名和密码方法

    前言 在大家使用github的过程中,一定会碰到这样一种情况,就是每次要push 和pull时总是要输入github的账号和密码,这样不仅浪费了大量的时间且降低了工作效率.在此背景下,本文在网上找了两 ...

  4. 用UBOOT自带loadb命令加载应用程序到SDRAM中运行的方法

    S3C44B0开发板中,用UBOOT自带loadb命令加载应用程序到SDRAM中运行的方法    1.开发板说明:  开发板上已有移植好的UBOOT运行.   2.交叉编译工具链为arm-linu-g ...

  5. 在Android项目中启用Java 8的部分特性--Lambda & Method References

    Android N发布时同时发布了一个新的编译工具Jack(AS2.1+支持),基于Jack我们可以使用Java 8 的部分特性,在低版本机器上能使用的更少,同时Jack也有诸多不完善,工具链的改变难 ...

  6. 怎样绕过oracle listener 监听的password设置

     怎样绕过oracle 监听的password设置: 1.找到监听进程pid ,并将它kill 掉 ps -ef|grep tns [oracle@lixora admin]$ ps -ef|gr ...

  7. cocos2d-x精灵移动的方法

    1.飞机发射子弹型 想要实现子弹的的飞行效果,又不想在每帧Update里计算位置,最好的方法调用CCMoveTo 例在发射子弹的时机,能够ccTouchBegan时: CCMoveTo* move = ...

  8. Android BroadcastReceiver实例Demo(有序广播的发送)

    上一篇简介了广播的发送,这篇主要介绍下,有序广播的发送. 设置完相关属性的时候,广播就会依照有序的方式进行发送: 发送顺序: 先发送第二条广播: 再发送第一条广播: 最后发送第三条广播. 代码例如以下 ...

  9. NYOJ 214 最长上升子序列nlogn

    普通的思路是O(n2)的复杂度,这个题的数据量太大,超时,这时候就得用nlogn的复杂度的算法来做,这个算法的主要思想是只保存有效的序列,即最大递增子序列,然后最后得到数组的长度就是最大子序列.比如序 ...

  10. Html.RenderPartial和Html.RenderAction的区别

    添加一个PartialController控制器 using System; using System.Collections.Generic; using System.Linq; using Sy ...