文章目录
主体
建立新项目
建立POCO 类
订单及订单项
public class Morder
{
public int ID { get; set; }
[Display(Name = "订单号")]
[Required]
public string orderNumber { get; set; }
public ICollection<MorderDetail> orderDetails { get; set; }
}
public class MorderDetail
{
public int ID { get; set; }
[Display(Name = "订单条目")]
[Required]
public string itemName { get; set; }
//下面两个建立关联,对应订单
public int MorderID { get; set; }
public virtual Morder order { get; set; }
}
添加新项->数据->ADO.NET数据实体->空CODE FIRST模型
mydb.cs中添加dbset:
public virtual DbSet<Morder> orders{ get; set; }
public virtual DbSet<MorderDetail> orderDetails { get; set; }
新建保存数据
using(var db=new mydb())
{
//主表
Morder od = new Morder();
od.orderNumber = "010025";
od.orderDetails = new List<MorderDetail>();
//从表
MorderDetail odd = new MorderDetail();
odd.itemName = "苹果";
od.orderDetails.Add(odd);
db.orders.Add(od);
//保存
db.SaveChanges();
}
删除数据
using (var db = new mydb())
{
var todel = db.orders.Where(p => p.orderNumber == "010025");
db.orders.RemoveRange(todel);
db.SaveChanges();
}
== 此处删除是级联删除,在删除主表数据时,自动删除从表数据。如果想禁用级联删除或允许部分级联删除,可以在mydb.cs中添加重写的OnModelCreating方法 ==
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// 禁用一对多级联删除
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
//但仍然可以指定某个表格可以级联删除
modelBuilder.Entity<MorderDetail>()
.HasRequired(t => t.order)
.WithMany(t => t.orderDetails)
.HasForeignKey(d => d.MorderID)
.WillCascadeOnDelete(false);
//上面的语句意思是:子表模型类MorderDetail
//.需要自己类定义中中有指向主表的属性order
//.order一对多到order.orderDetails属性指向的子表
//.通过子表外键MorderID
//可以级联删除
//上面四个括号内分别填:子表模型类名,子表模型中指向父表的属性名,父表模型中指向子表的属性,子表模型指向父表的id属性
}
级联查询
var l=db.orders.ToList();
上面代码可以加载主表数据。但每一个的orderDetails=null
var l=db.orders.Include(p=>p.orderDetails).ToList();
上面代码可以显式加载从表数据
EF的三种加载数据方式
EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Loading都是延迟加载。
(一)延迟加载(默认):
Lazy Loading使用的是动态代理,默认情况下,如果POCO类满足以下两个条件,EF就使用Lazy Loading:
- POCO类是Public且不为Sealed。
- 导航属性标记为Virtual。
关闭Lazy Loading,可以将LazyLoadingEnabled设为false,如果导航属性没有标记为virtual,Lazy Loading也是不起作用的。
(二)贪婪加载:
不设置导航属性为virtual,并且对导航属性使用Include,Eager Loading使用Include方法关联预先加载的实体。
(三)显示加载:
不设置导航属性为virtual,并且对导航属性使用Reference(单个对象).Load()或Collection(对象集).Load()。Explicit Loading使用Entry方法,对于集合使用Collection,单个实体则使用Reference。
var cls = query.Single();
db.Entry(cls).Collection(v => v.Student).Load();//加载集合使用Collection方法
var student = db.Student.First();
db.Entry(student).Reference(v => v.Classes).Load();//加载单个实体使用Reference方法
参考链接
其它
设置初始化数据
建立初始化类
class DBinitializer : DropCreateDatabaseAlways<MyModel>
{
protected override void Seed(MyModel context)
{
base.Seed(context);
var c = new MODEL.Company();
c.CompanyName = "a";
c.ContactMan = "b";
context.Companys.Add(c);
context.SaveChanges();
}
}
//在mymodel.cs(dbcontext类)中添加初始化语句:
public MyModel() : base("name=MyModel")
{
Database.SetInitializer(new DBinitializer());
}
迁移:
迁移是指,在开发完成以后,用户使用过程中会增加数据,后来提出需求,更改了模型,需要将原有数据迁移动新数据库并修改表格结构。
所在交付用户使用前,就要进行一次迁移准备工作,将当前的数据库表状态记录下来,以后在迁移时自动对比模型更改并产生迁移脚本,以实现最大限度的用户数据保留。
在NUGET包控制台中运行命令:
Enable-Migrations -EnableAutomaticMigrations
执行成功后,Portal控制台应用程序代码结构中,添加Migrations文件夹,并生成类文件Configuration.cs。
然后在控制台下利用Add-Migration 与Update-Database 命令更新数据的变更,生产的SQL文件可以进行修改,以保留数据,具体用法请百度