一篇文章告诉你如何使用EF CodeFirst做增删改查

一、修改数据

其实修改涉及的内容挺多的,是相对于其他操作来说比较繁琐。也是本文的重头戏。

虽然都是基础内容,但是也是值得细细品味的。

1、最简单直接的修改数据就是从数据库里检索出数据修改相应的字段即可

数据表:

 

Code:

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Two old_entity = db.Twos.Single(t => t.Text == "90");

old_entity.Text = "update";

db.SaveChanges();

}

结果:

 

2、直接更新不需要检索出数据

数据表:

 

Code:

通过修改实体的状态来实现

ApplicationDbContext.Two entity = new ApplicationDbContext.Two() { TwoId = 1, Text = "update" };

using (var db = new ApplicationDbContext())

{

db.Entry(entity).State = EntityState.Modified;

db.SaveChanges();

}

结果:

 

这个方式有个不好地方,图中很明显的标注出来了,就是会一股脑更新全部字段,没有值就被更新成NULL。

3、指定字段更新

数据表:

 

Code

修改实体状态为Unchanged.

设置指定属性的状态为修改

ApplicationDbContext.Two entity = new ApplicationDbContext.Two() { TwoId = 1, Text = "update" };

using (var db = new ApplicationDbContext())

{

db.Entry(entity).State = EntityState.Unchanged;

db.Entry(entity).Property("Text").IsModified = true;

db.SaveChanges();

}

结果:

 

4、禁用验证实体的有效性

有时我们在更新时有些字段是不更新的,但是这些字段又可能会有一些验证特性,比如不可以为空,这样我们在保存时会因实体验证不通过而报错。

实体:

Uu是必须的,不可为空

public class MyFirst

{

public int MyFirstId { get; set; }

public string Text { get; set; }

[Required]

public string Uu { get; set; }

}

Code:

ApplicationDbContext.MyFirst entity = new ApplicationDbContext.MyFirst() { MyFirstId = 1, Text = "update" };

using (var db = new ApplicationDbContext())

{

db.Entry(entity).State = EntityState.Unchanged;

db.Entry(entity).Property("Text").IsModified = true;

db.SaveChanges();

}

结果:

因没通过Uu的特性的验证而报错了,我们只更新了Text,没有给Uu赋值,但是Uu又是不可以为空的

 

只要我们在保存前取消这种验证就可以了,在保存后恢复验证

修改后的Code:

ApplicationDbContext.MyFirst entity = new ApplicationDbContext.MyFirst() { MyFirstId = 1, Text = "update" };

using (var db = new ApplicationDbContext())

{

db.Entry(entity).State = EntityState.Unchanged;

db.Entry(entity).Property("Text").IsModified = true;

db.Configuration.ValidateOnSaveEnabled = false;

db.SaveChanges();

db.Configuration.ValidateOnSaveEnabled = true;

}

数据表:

 

结果:

 

5、在不同的上下文中更新数据

情况一

Code:

ApplicationDbContext.Two entity;

using(var db1=new ApplicationDbContext())

{

entity = db1.Twos.Single(m => m.Text == "90");

}

entity.Text = "update";

using (var db = new ApplicationDbContext())

{

DbEntityEntry entry = db.Entry(entity);

entry.State = EntityState.Modified;

db.SaveChanges();

}

在这种场景下更新有一个问题是,数据会全部更新,并不是我们指定的Text更新,原因是不在一个上下文中,在另一个上下文中没有上一个上下文的状态,所以更新时没法判定就全部更新了。

数据图:

 

在db1获取数据时设置一个断点,手动修改数据库后的数据表:

 

结果数据:

会发现数据都被更新了,对比第二张图

 

情况二

Code:

ApplicationDbContext.Two entity;

using(var db1=new ApplicationDbContext())

{

entity = db1.Twos.Single(m => m.Text == "90");

}

entity.Text = "update";

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Two entity1 = db.Twos.Single(m => m.Text == "90");

DbEntityEntry entry = db.Entry(entity);

entry.State = EntityState.Modified;

db.SaveChanges();

}

在这种场景下,与上面的区别是第二个上下文也检索了数据,这种情况就是报错,原因就是同一个上下文中不能出现主键值相同的实体。db检索数据时存在了一个实体在上下文中,又要把db1检索出的实体添加到db上下文中,一但主键值相同就会报错

 

解决上述情况:

关键点是entry.CurrentValues.SetValues(entity);设置当前上下文实体的值。

Code:

ApplicationDbContext.Two entity;

using(var db1=new ApplicationDbContext())

{

entity = db1.Twos.Single(m => m.Text == "90");

}

entity.Text = "update";

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Two entity1 = db.Twos.Single(m => m.Text == "90");

DbEntityEntry entry = db.Entry(entity1);

entry.CurrentValues.SetValues(entity);

db.SaveChanges();

}

数据图:

 

在db获取数据时设置一个断点,手动修改数据库后的数据表:

 

结果数据:

会发现只有指定的数据更新了,对比第二张图

 

6、同一个上下文中有实体存在的情况下用外部数据更新

Code:

ApplicationDbContext.Two entity= new ApplicationDbContext.Two() { TwoId = 1, Text = "update" };           

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Two entity1 = db.Twos.Single(m => m.Text == "90");

DbEntityEntry entry = db.Entry(entity);

entry.State = EntityState.Modified;

db.SaveChanges();

}

会报错,原因和上面情况一样,上下文中出现了主键一样的多个实体,本来有一个实体了,又加载了一个主键一样的实体,就报错了。

 

用上述方法解决试试看

Code:

ApplicationDbContext.Two entity= new ApplicationDbContext.Two() { TwoId = 1, Text = "update" };           

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Two entity1 = db.Twos.Single(m => m.Text == "90");

DbEntityEntry entry = db.Entry(entity1);

entry.CurrentValues.SetValues(entity);

db.SaveChanges();

}

没有报错,成功更新数据,但是问题是全部数据都被更新,不是我们指定的数据更新

结果数据:

 

尝试使用指定属性更新:

结果你会发现数据没有发生任何变化,原因是entry.State = EntityState.Unchanged;把ntry.CurrentValues.SetValues(entity);改变得值有还原回去了。

ApplicationDbContext.Two entity= new ApplicationDbContext.Two() { TwoId = 1, Text = "update" };           

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Two entity1 = db.Twos.Single(m => m.Text == "90");

DbEntityEntry entry = db.Entry(entity1);

entry.CurrentValues.SetValues(entity);

entry.State = EntityState.Unchanged;

entry.Property("Text").IsModified = true;

db.SaveChanges();

}

解决上述问题:

如果要解决上述问题应该使用ObjectContext的ObjectStateEntry设置当前值,状态,以及指定修改的属性

Code:

ApplicationDbContext.Two entity= new ApplicationDbContext.Two() { TwoId = 1, Text = "update" };           

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Two entity1 = db.Twos.Single(m => m.Text == "90");

ObjectContext objectContext = ((IObjectContextAdapter)db).ObjectContext;

ObjectStateEntry entry = objectContext.ObjectStateManager.GetObjectStateEntry(entity1);

entry.ApplyCurrentValues(entity);

entry.ChangeState(EntityState.Unchanged);

entry.SetModifiedProperty("Text");

db.SaveChanges();

}

结果数据:

 

对上上述更新方式做一个封装

public static class Test

{

//指定更新

public static void Update<TEntity>(this DbContext dbcontext,

Expression<Func<TEntity, object>> propertyExpression,

params TEntity[] entities) where TEntity : EntityBase

{

if (propertyExpression == null)

{

throw new ArgumentException("propertyExpression");

}

if (entities == null)

{

throw new ArgumentException("entities");

}

ReadOnlyCollection<MemberInfo> memberInfos = ((dynamic)propertyExpression.Body).Members;

foreach (TEntity entity in entities)

{

try

{

DbEntityEntry<TEntity> entry = dbcontext.Entry(entity);

entry.State = EntityState.Unchanged;

foreach (var memberInfo in memberInfos)

{

entry.Property(memberInfo.Name).IsModified = true;

}

}

catch

{

TEntity originalEntity = dbcontext.Set<TEntity>().Single(m => m.Id == entity.Id);

ObjectContext objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;

ObjectStateEntry objectEntry = objectContext.ObjectStateManager.GetObjectStateEntry(originalEntity);

objectEntry.ApplyCurrentValues(entity);

objectEntry.ChangeState(EntityState.Unchanged);

foreach (var memberInfo in memberInfos)

{

objectEntry.SetModifiedProperty(memberInfo.Name);

}

}

}

}

//提交保存

public static int SaveChanges(this DbContext dbContext, bool validateOnSaveEnabled)

{

bool isReturn = dbContext.Configuration.ValidateOnSaveEnabled != validateOnSaveEnabled;

try

{

dbContext.Configuration.ValidateOnSaveEnabled = validateOnSaveEnabled;

return dbContext.SaveChanges();

}

finally

{

if (isReturn)

{

dbContext.Configuration.ValidateOnSaveEnabled = !validateOnSaveEnabled;

}

}

}

//全部更新

public static void Update1<TEntity>(this DbContext dbContext, params TEntity[] entities) where TEntity : EntityBase

{

if (dbContext == null) throw new ArgumentException("dbContext");

if (entities == null) throw new ArgumentException("entities");

foreach(TEntity entity in entities)

{

DbSet<TEntity> dbSet = dbContext.Set<TEntity>();

try

{

DbEntityEntry<TEntity> entry = dbContext.Entry(entity);

if (entry.State == EntityState.Detached)

{

entry.State = EntityState.Modified;

}

}

catch

{

TEntity oldEntity = dbSet.Find(entity.Id);

dbContext.Entry(oldEntity).CurrentValues.SetValues(entity);

}

}

}

}

public class EntityBase

{

public int Id { get; set; }

}

public class Three : EntityBase

{

public string Text { get; set; }

public string Uu { get; set; }

}

封装后的使用实例:

pplicationDbContext.Three entity= new ApplicationDbContext.Three() { Id = 1, Text = "update" };           

using (var db = new ApplicationDbContext())

{

ApplicationDbContext.Three entity1 = db.Threes.Single(m => m.Text == "90");

db.Update<ApplicationDbContext.Three>(m => new { m.Text }, entity);

db.SaveChanges();

}

至此更新部分已经全部完毕

Ps:其实扩展方法update有个坑,就是一但出现并发时就会报错走catch,而其实不是想要的结果,这是个忽略的地方,并发应该抛出错误,用catch是忽略了并发的情况...额...

二、添加数据

简单明了没有啥好说的

Code:

ApplicationDbContext.Three entity = new ApplicationDbContext.Three() { Text = "我哦哦哦" };           

using (var db = new ApplicationDbContext())

{

db.Threes.Add(entity);

db.SaveChanges();

}

数据图:

 

三、删除数据

简单明了没啥好说的

通过Attach把实体加载到上下文,关键点就是实体要存在于上下文中

Code:

ApplicationDbContext.Three entity = new ApplicationDbContext.Three() { Id=2 };           

using (var db = new ApplicationDbContext())

{

db.Threes.Attach(entity);

db.Threes.Remove(entity);

db.SaveChanges();

}

Code:

ApplicationDbContext.Three entity = new ApplicationDbContext.Three() { Id = 3 };     

using (var db = new ApplicationDbContext())

{

db.Entry(entity).State = EntityState.Deleted;

db.SaveChanges();

}

四、查询

1、简单查询

int[] scores = { 90, 71, 82, 93, 75, 82 };

 

IEnumerable<int> scoreQuery =

from score in scores

where score > 80

orderby score descending

select score;

 

foreach (int testScore in scoreQuery)

{

Console.WriteLine(testScore);

}

//输出结果:93 90 82 82

2、分组查询

var queryLastNames =

from student in students

group student by student.LastName into newGroup

orderby newGroup.Key

select newGroup;

3、内联查询

var query = from person in people

join pet in pets on person equals pet.Owner

select new { OwnerName = person.FirstName, PetName = pet.Name };

4、分组连接

结果是:一个名字对应一个集合

var query = from person in people

join pet in pets on person equals pet.Owner into gj

select new { OwnerName = person.FirstName, Pets = gj };

5、外联查询

var query = from person in people

join pet in pets on person equals pet.Owner into gj

from subpet in gj.DefaultIfEmpty()

select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) };

6、在查询中处理null

var query1 =

from c in categories

where c != null

join p in products on c.ID equals

(p == null ? null : p.CategoryID)

select new { Category = c.Name, Name = p.Name };

 

var query =

from o in db.Orders

join e in db.Employees

on o.EmployeeID equals (int?)e.EmployeeID

select new { o.OrderID, e.FirstName };

7、在查询中处理异常

IEnumerable<int> dataSource;

try

{

dataSource = GetData();

}

catch (InvalidOperationException)

{

Console.WriteLine("Invalid operation");

goto Exit;

}

var query = from i in dataSource

select i * i;

foreach (var i in query)

Console.WriteLine(i.ToString());

Exit:

Console.WriteLine("Press any key to exit");

 

string[] files = { "fileA.txt", "fileB.txt", "fileC.txt" };

var exceptionDemoQuery =

from file in files

let n = SomeMethodThatMightThrow(file)

select n;

try

{

foreach (var item in exceptionDemoQuery)

{

Console.WriteLine("Processing {0}", item);

}

catch (InvalidOperationException e)

{

Console.WriteLine(e.Message);

}

更多关于查询请查考MSDN,里面很详细

https://msdn.microsoft.com/zh-cn/library/bb384065.aspx

 

转载于:https://www.cnblogs.com/c-o-d-e/p/5180830.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的使用 .Net Core 和 Entity Framework (EF) 的增删改查案例: 首先,创建一个 ASP.NET Core Web 应用程序。在 Visual Studio 中,选择“创建新项目”,然后选择“ASP.NET Core Web 应用程序”。 接下来,选择一个模板,例如“Web 应用程序 (Model-View-Controller)”模板,然后点击“创建”。 在应用程序中,我们需要安装 Entity Framework Core。在“解决方案资源管理器”中右键单击项目,然后选择“管理 NuGet 包”选项。在“NuGet 包管理器”中搜索“Microsoft.EntityFrameworkCore”,然后安装它。 创建一个名为“AppDbContext.cs”的新类,用于定义数据库上下文。在该类中,我们需要指定要使用数据库提供程序,以及要使用数据库连接字符串。 ```csharp using Microsoft.EntityFrameworkCore; namespace YourAppName.Models { public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<User> Users { get; set; } } } ``` 接下来,创建一个名为“User.cs”的新类,用于定义用户模型。 ```csharp namespace YourAppName.Models { public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } } ``` 现在,我们可以创建控制器和视图来执行 CRUD 操作。 在“控制器”文件夹中,创建一个名为“UserController.cs”的新控制器。在控制器中,我们需要注入“AppDbContext”依赖项,并定义以下动作: - Index:显示所有用户。 - Details:显示单个用户的详细信息。 - Create:显示创建用户的表单。 - Edit:显示编辑用户的表单。 - Delete:显示删除用户的确认页面。 - CreatePost:处理创建用户的 POST 请求。 - EditPost:处理编辑用户的 POST 请求。 - DeletePost:处理删除用户的 POST 请求。 ```csharp using System.Linq; using Microsoft.AspNetCore.Mvc; using YourAppName.Models; namespace YourAppName.Controllers { public class UserController : Controller { private readonly AppDbContext _dbContext; public UserController(AppDbContext dbContext) { _dbContext = dbContext; } public IActionResult Index() { var users = _dbContext.Users.ToList(); return View(users); } public IActionResult Details(int id) { var user = _dbContext.Users.FirstOrDefault(u => u.Id == id); return View(user); } public IActionResult Create() { return View(); } [HttpPost] public IActionResult CreatePost(User user) { _dbContext.Users.Add(user); _dbContext.SaveChanges(); return RedirectToAction("Index"); } public IActionResult Edit(int id) { var user = _dbContext.Users.FirstOrDefault(u => u.Id == id); return View(user); } [HttpPost] public IActionResult EditPost(User user) { var existingUser = _dbContext.Users.FirstOrDefault(u => u.Id == user.Id); if (existingUser != null) { existingUser.Name = user.Name; existingUser.Age = user.Age; _dbContext.SaveChanges(); } return RedirectToAction("Index"); } public IActionResult Delete(int id) { var user = _dbContext.Users.FirstOrDefault(u => u.Id == id); return View(user); } [HttpPost] public IActionResult DeletePost(int id) { var user = _dbContext.Users.FirstOrDefault(u => u.Id == id); if (user != null) { _dbContext.Users.Remove(user); _dbContext.SaveChanges(); } return RedirectToAction("Index"); } } } ``` 在“视图”文件夹中,创建一个名为“Index.cshtml”的新视图,用于显示所有用户。在视图中,我们需要遍历所有用户,并为每个用户显示详细信息、编辑和删除链接。 ```html @model IEnumerable<User> <table> <thead> <tr> <th>ID</th> <th>Name</th> <th>Age</th> <th></th> </tr> </thead> <tbody> @foreach (var user in Model) { <tr> <td>@user.Id</td> <td>@user.Name</td> <td>@user.Age</td> <td> <a href="@Url.Action("Details", new { id = user.Id })">Details</a> | <a href="@Url.Action("Edit", new { id = user.Id })">Edit</a> | <a href="@Url.Action("Delete", new { id = user.Id })">Delete</a> </td> </tr> } </tbody> </table> <a href="@Url.Action("Create")">Create new user</a> ``` 创建一个名为“Details.cshtml”的新视图,用于显示单个用户的详细信息。 ```html @model User <div> <h1>@Model.Name</h1> <p>Age: @Model.Age</p> </div> <a href="@Url.Action("Index")">Back to list</a> ``` 创建一个名为“Create.cshtml”的新视图,用于显示创建用户的表单。 ```html @model User <form asp-action="CreatePost"> <div> <label>Name:</label> <input asp-for="Name" /> </div> <div> <label>Age:</label> <input asp-for="Age" /> </div> <button type="submit">Create</button> </form> <a href="@Url.Action("Index")">Back to list</a> ``` 创建一个名为“Edit.cshtml”的新视图,用于显示编辑用户的表单。 ```html @model User <form asp-action="EditPost"> <div> <label>ID:</label> <input asp-for="Id" readonly /> </div> <div> <label>Name:</label> <input asp-for="Name" /> </div> <div> <label>Age:</label> <input asp-for="Age" /> </div> <button type="submit">Save</button> </form> <a href="@Url.Action("Index")">Back to list</a> ``` 创建一个名为“Delete.cshtml”的新视图,用于显示删除用户的确认页面。 ```html @model User <div> <h1>Are you sure you want to delete this user?</h1> <p>@Model.Name (age @Model.Age)</p> </div> <form asp-action="DeletePost" method="post"> <input type="hidden" name="id" value="@Model.Id" /> <button type="submit">Delete</button> </form> <a href="@Url.Action("Index")">Cancel</a> ``` 现在,我们已经完成了一个简单的使用 .Net Core 和 Entity Framework 的增删改查案例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值