从 ASP.NET Core 2.2 更新 SQL Server 中的上下文

Posted

技术标签:

【中文标题】从 ASP.NET Core 2.2 更新 SQL Server 中的上下文【英文标题】:Update context in SQL Server from ASP.NET Core 2.2 【发布时间】:2019-08-28 23:23:16 【问题描述】:
_context.Update(v) ;
_context.SaveChanges();

当我使用此代码时,SQL Server 会添加一条新记录,而不是更新 当前上下文

[HttpPost]
public IActionResult PageVote(List<string> Sar)

    string name_voter = ViewBag.getValue = TempData["Namevalue"];

    int count = 0;

    foreach (var item in Sar)
    
        count = count + 1;
    

    if (count == 6)
    
        Vote v = new Vote()
                 
                    VoteSarparast1 = Sar[0],
                    VoteSarparast2 = Sar[1],
                    VoteSarparast3 = Sar[2],
                    VoteSarparast4 = Sar[3],
                    VoteSarparast5 = Sar[4],
                    VoteSarparast6 = Sar[5],
                 ;

        var voter = _context.Votes.FirstOrDefault(u => u.Voter == name_voter && u.IsVoted == true);

        if (voter == null)
        
            v.IsVoted = true;
            v.Voter = name_voter;
            _context.Add(v);
            _context.SaveChanges();

            ViewBag.Greeting = "رای شما با موفقیت ثبت شد";
            return RedirectToAction(nameof(end));
        

        v.IsVoted = true;
        v.Voter = name_voter;

        _context.Update(v);
        _context.SaveChanges();

        return RedirectToAction(nameof(end));
    
    else
    
        return View(_context.Applicants.ToList());
    

【问题讨论】:

欢迎来到 SO :)。我们需要更多代码来帮助您。特别是,v 来自哪里?是参数吗?您面临的问题是:DbContext 不知道v,这意味着它没有跟踪它。当您致电Update 时,它会在内部检查并说:嗯.. 我不认识这个人,所以我最好插入它。要修复,你必须先加载它,然后调用Update public DatabaseContext(DbContextOptions options) : base(options) public DbSet Roles get;放; 公共 DbSet 用户 获取;放; 公共 DbSet 投票 获取;放; public DbSet 申请者 get;放; //// public HomeController(DatabaseContext context) _context = context; ...... //// 投票 v = new Vote() .. 这就是为什么。 v 是一个新实例,如果没有您告诉它,DbContext 无法更新它。此外,v 必须有一个 Id,以便 DbContext 可以找到它。请将代码放在您的问题中,而不是在 cmets 中,因为它很难阅读。 _context.SaveChanges() 跟踪所有更改,当实体发生更改时,无需调用 _context.Update(),_context.SaveChanges() 高效,您的实体将被更新,请注意Entity Framework Update @reza.nadrian 确保将我的答案标记为已接受,如果它可以帮助您解决问题。这就是你用虚假的互联网积分“感谢我”的方式。 :D 【参考方案1】:

您需要告诉DbContext 您的实体。如果你做var vote = new Vote() vote 没有IdDbContext 看到这个并认为你想要 Add 一个新实体,所以它只是这样做。 DbContext 跟踪您从中加载的所有实体,但由于这只是一个新实例,它不知道它。

要实际执行更新,您有两种选择:

1 - 以某种方式从数据库中加载Vote;如果你得到一个 ID,用它来找到它。

// Loads the current vote by its id (or whatever other field..)
var existingVote = context.Votes.Single(p => p.Id == id_from_param);

// Perform the changes you want..
existingVote.SomeField = "NewValue";                

// Then call save normally.
context.SaveChanges();

2 - 或者,如果您不想从 Db 加载它,您必须手动告诉DbContext该怎么做:

// create a new "vote"...
var vote = new Vote

    // Since it's an update, you must have the Id somehow.. so you must set it manually
    Id = id_from_param,

    // do the changes you want. Be careful, because this can cause data loss!
    SomeField = "NewValue"
;

// This is you telling the DbContext: Hey, I control this entity. 
// I know it exists in the DB and it's modified
context.Entry(vote).State = EntityState.Modified;

// Then call save normally.
context.SaveChanges();

这两种方法中的任何一种都可以解决您的问题,但我建议您阅读更多有关实体框架如何工作的信息。这对于您的应用程序的成功(和性能)至关重要。特别是上面的option 2 可能会导致很多问题。 DbContext 跟踪实体是有原因的,所以您不必这样做。这非常复杂,而且事情可能很快就会向南发展。

一些链接给你: ChangeTracker in Entity Framework Core Working with Disconnected Entity Graph in Entity Framework Core

【讨论】:

以上是关于从 ASP.NET Core 2.2 更新 SQL Server 中的上下文的主要内容,如果未能解决你的问题,请参考以下文章

从 ASP.NET Core 2.2 升级到 3.0

无法使用 ASP .NET Core 更新 SQL 位列

ASP.NET Core 2.2 中的 Azure AD 身份验证

ASP.NET Core 2.2 MVC MapRoute 项目到 ASP.NET 3.0 端点 MapAreaControllerRoute “找不到此本地主机页面”

如何使用 Asp.Net Core 2.2 / IdentityServer4 / SP.NET Core Identity 手动散列密码

asp.Net core 2.2中的多种身份验证方法