一.不查询数据库,主键必须赋值

为避免先查询数据库,可以直接将 被修改的实体对象 添加到 EF中管理(此时为附加状态Attached),并手动设置其为未修改状态(Unchanged),同时设置被修改的实体对象 的 包装类对象 对应属性为修改状态。

优点:修改前不需要查询数据库。

1.创建修改的 实体对象

UserInfoes userInfonew = new UserInfoes()
{
UserId=userInfo.UserId,
Email = userInfo.Email,
FirstName = userInfo.FirstName,
LastName = userInfo.LastName,
LastUpdateBy = GetCurrentUserGuid(),
LastUpdate = DateTime.Now
}; 

2.添加到EF管理容器中,并获取 实体对象 的伪包装类对象

如果使用 Entry 附加 实体对象到数据容器中,则需要手动 设置 实体包装类的对象 的 状态为 Unchanged.

或者使用 Attach( Attach方法:将给定实体以 System.Data.EntityState.Unchanged 状态附加到上下文中从解释可以看出Attach方法主要目的就是把一个没有被dbContext跟踪的对象附加到dbCotext中使其被dbContext跟踪).

下面2句选择其一即可。

db.Entry(userInfonew).State = System.Data.Entity.EntityState.Unchanged;

或者

db.UserInfoes.Attach(userInfonew);

3.更新字段

①更新全部字段:

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

②更新部分字段:

db.Entry(userInfonew).Property(x => x.Email).IsModified = true;

4.更新到数据库

db.SaveChanges();

特别提醒:主键必须赋值,如果不赋值,会报错"Store update, insert, or delete statement affected an unexpected number of rows (0)…"

二.先查询实体再更新

1. 查询实体后更新数据库

①.先查询要修改的原数据(注意此处不要加AsNoTracking(),加了无法更新)

var userInfoes= db.UserInfoes.Where(a => a.UserId== model.UserId).FirstOrDefault(); 

②.更新字段的值

userInfoes.LastUpdateBy = GetCurrentUserGuid();

userInfoes.LastUpdate = DateTime.Now;

③.更新到数据库

db.SaveChanges(); 

注意:EF查询出来的实体是无法更新主键的值
否则会报如下错误:
在这里插入图片描述
2. 查询实体后不使用查询的实体,手动创建实体

 var query = await (from a in db.MesMachineConfig
                            join c in db.Site_LinePosition
                            on new {A = a.LineNum,B = a.MCPosition} equals new {A= c.LineNum,B=c.MCPosition}
                         join b in db.DGHKROneReelNumManagerParamsSettings
                             on a.MachineNum equals b.MachineNum into rightRow
                         from rw in rightRow.DefaultIfEmpty()
                         where a.Enable == "Y" && a.Size == dghkrOneReelNumManagerParamsSettingsDto.Size
                        select new 
                        {
                            a,
                            rw
                        }
                        /*这里不加AsNoTracking会报错"相同类型的其他实体已具有相同的主键值"
                            )/*.AsNoTracking()*/.ToListAsync();

                    query.ForEach(p =>
                    {
                        var mapResult = dghkrOneReelNumManagerParamsSettingsDto.MapTo<DGHKROneReelNumManagerParamsSettings>();
                        mapResult.MachineNum = p.a.MachineNum;
                        //添加
                        if (p.rw == null)
                        {
                            db.Add(mapResult);
                        }
                        //更新
                        else
                        {
                            db.Update(mapResult);
                        }
                    });

Attach的时候会报如下错误:因为相同类型的其他实体已具有相同的主键值。在使用 “Attach” 方法或者将实体的状态设置为 “Unchanged” 或 “Modified” 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为。
在这里插入图片描述解决办法: 查询的时候加AsNoTracking()

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐