共计 4617 个字符,预计需要花费 12 分钟才能阅读完成。
导读 | 这篇文章介绍了 Entity Framework 使用 DBContext 实现增删改查的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 |
有一段时间没有更新博客了,赶上今天外面下雨,而且没人约球,打算把最近对 Entity Framework DBContext 使用的心得梳理一下,早些时候在网上简单查过,对于最新版本的 EF 并没有类似的知识梳理类文章,希望对大家有所帮助。
我为什么讨厌 Code first 和 DB first 呢?首先 Code first 是先写代码,数据库完全由代码生成,开发阶段尚可,一旦到了产品发布阶段,如果需要添加字段,我们总不能用 visual studio 去生产环境上去更新数据库吧,听起来就很可怕。而且另外的一个问题自动是生成的数据库脚本也不可控,还不如自己提前设计好。DB first 也好不了哪去,反向转过来的代码包含很多没有用的文件,而且数据库的更新还要重新走 Model 生成过程,简直无法理解为什么会有这样的设计。说了这么多,怎么解决呢?
数据库和领域模型分开设计,按照对应关系映射字段,使用自定义链接字串,既不使用领域模型生成数据库,也不用数据库生成领域模型,示例代码如下,SQL Code 以 Destinations 和 TTable 表为例:
CREATE TABLE [DBO].[Destinations] | |
([DestinationId] [int] PRIMARY KEY NOT NULL, | |
[Name] [nvarchar](max) NULL, | |
[Country] [nvarchar](max) NULL, | |
[Description] [nvarchar](max) NULL, | |
[Photo] [varbinary](max) NULL |
CREATE TABLE [TTT].[TTable] | |
([Id] [int] PRIMARY KEY NOT NULL, | |
[Name] [nvarchar](max) NULL) |
Model Class:
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Model | |
{ | |
public class Destination | |
{public int DestinationId { get; set;} | |
public string Name {get; set;} | |
public string Country {get; set;} | |
public string Description {get; set;} | |
public byte[] Photo { get; set;} | |
public List Lodgings {get; set;} | |
} | |
public class Lodging | |
{public int LodgingId { get; set;} | |
public string Name {get; set;} | |
public string Owner {get; set;} | |
public bool IsResort {get; set;} | |
public Destination Destination {get; set;} | |
} | |
public class TTable | |
{public int Id { get; set;} | |
public string Name {get; set;} | |
} | |
} |
Connect String:
DB Context:
using System.Data.Entity; | |
using System.Data.Entity.ModelConfiguration; | |
using Model; | |
namespace DataAccess | |
{public class TTableConfiguration : EntityTypeConfiguration | |
{public TTableConfiguration() | |
{this.ToTable("TTable", "TTT"); | |
} | |
} | |
public class BreakAwayContext : DbContext | |
{protected override void OnModelCreating(DbModelBuilder modelBuilder) | |
{modelBuilder.Configurations.Add(new TTableConfiguration()); | |
} | |
public BreakAwayContext(string connString) : base(connString) | |
{ } | |
public DbSet Destinations {get; set;} | |
public DbSet Lodgings {get; set;} | |
public DbSet TTables {get; set;} | |
} | |
} |
比如本文的 TTable 表是在 TTT Schema 下面的,而其他表示设计在 DBO 下面,最方便的方式是使用 fluent API, 具体代码如请参见 TTableConfiguration Class 和 OnModelCreating() 方法,可配置的粒度非常细,比如可以配置领域模型和数据库的哪个 Schema 的哪张表的哪一列对应,本文是将 TTable 类的数据库表配置为了 TTT Schema 下的 TTable 表,
public class TTableConfiguration : EntityTypeConfiguration | |
{public TTableConfiguration() | |
{this.ToTable("TTable", "TTT"); | |
} | |
} |
public static int Insert() | |
{ | |
var destination = new Destination | |
{ | |
Country = "Chs", | |
Description = "Chs is the language package", | |
Name = "xsss" | |
}; | |
using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings["BAContext"].ConnectionString)) | |
{var rt = context.Destinations.Add(destination); | |
context.SaveChanges(); | |
return rt.DestinationId; | |
} | |
} | |
public static void Update(Destination destIn) | |
{using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings["BAContext"].ConnectionString)) | |
{var dest = context.Destinations.Where(a => a.DestinationId == destIn.DestinationId).Single(); | |
dest.Name = destIn.Name; | |
context.SaveChanges();} | |
} | |
public static void Delete(int destId) | |
{using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings["BAContext"].ConnectionString)) | |
{var destination = new Destination() {DestinationId = destId}; | |
context.Destinations.Attach(destination); | |
context.Destinations.Remove(destination); | |
context.SaveChanges();} | |
} | |
public static Destination Query(int destId) | |
{using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings["BAContext"].ConnectionString)) | |
{IQueryable dest = context.Destinations.Where(a => a.DestinationId == destId); | |
return dest.Single();} | |
} |
public static void TransactionOps() | |
{using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings["BAContext"].ConnectionString)) | |
{using (var dbContextTransaction = context.Database.BeginTransaction()) | |
{ | |
try | |
{ | |
var destination = new Destination | |
{ | |
Country = "Chs", | |
Description = "Chs is the language package", | |
Name = "xs2s" | |
}; | |
var destId = context.Destinations.Add(destination); | |
context.SaveChanges(); | |
context.Destinations.Attach(destId); | |
context.Destinations.Remove(destId); | |
context.SaveChanges(); | |
dbContextTransaction.Commit();} | |
catch (System.Exception ex) | |
{dbContextTransaction.Rollback(); | |
System.Console.WriteLine(ex.ToString()); | |
} | |
} | |
} | |
} |
public static List QueryPaging(int pageIndex, int pageSize, Expression> whereLambda, Expression> orderBy) | |
{using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings["BAContext"].ConnectionString)) | |
{return context.Destinations.Where(whereLambda).OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();} | |
} |
本文对最新版本的 Entity Framework 进行增删改查操作给出了详尽的解释,并且给出了数据库和领域模型代码分开设计的完整解决方案,同时介绍了手动数据库表和领域模型映射,数据库事务实现,分页查询等常用功能,希望对大家有所帮助。
