【问题标题】:Entity Framework - How to add db entries without a form实体框架 - 如何在没有表单的情况下添加数据库条目
【发布时间】:2021-04-22 18:25:03
【问题描述】:

通常我使用“创建”表单添加新的数据库条目,就像给你的模板一样:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "MyObjectProperties")] MyObject MyObjectName)
{
    if (ModelState.IsValid)
    {
        db.MyObjects.Add(MyObjectName);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(MyObjectName);
}

效果很好。但是,我正在尝试删除数据库中的所有条目,然后再一一添加。目的是在表格中填写一年中每周的截止日期,此方法将重置截止日期并设置给定年份的正确日期。这是执行该任务的方法:

public bool ResetDeadlines()
{
    //db.Canteen_Deadlines.RemoveRange(db.Canteen_Deadlines);

    int monthOfLastWeek = 1;
    DateTime deadlineDate;
    int weekOfMonth = 0;
    int year = DateTime.Now.Year;

    for (var i = 1; i < 53; i++)
    {
        if (i == 1)
            year += 1;
        else
            year = DateTime.Now.Year;

        deadlineDate = GetThursdayOfWeek(year, i).AddDays(-7); //Gets the thursday of the week before, because that is the deadline for that week.
        weekOfMonth = monthOfLastWeek < deadlineDate.Month ? 1 : weekOfMonth + 1;

        var newDeadline = new Canteen_Deadlines
        {
            N = DaysFromNewYear(year, deadlineDate),
            DeadlineDate = deadlineDate,
            WeekNo = (byte)i,
            MonthNo = (byte)deadlineDate.Month,
            QuarterNo = (byte)GetQuarterNumber(deadlineDate.Month),
            YearNo = (short)year,
            DayofWeek = 4,
            LastDowInMonth = IsLastDoWInMonth(deadlineDate),
            DoWAsc = (byte)weekOfMonth
        };

        db.Canteen_Deadlines.Add(newDeadline);
        //db.Entry(newDeadline).State = EntityState.Added;
        db.SaveChanges();

        monthOfLastWeek = deadlineDate.Month;
    }

    return true;
}

当我执行db.SaveChanges(); 时,问题就出现了。它会给我一个DbUpdateConcurrencyException,说数据库中的所有行都没有受到影响。我似乎无法弄清楚我的方法和模板创建方法之间的区别。其他在线帖子更关注使用模板创建方法时出现的这个问题,以及人们没有在他们的 ID 上使用“Html.HiddenFor”。这对我来说不是一个可行的解决方案,因为我没有使用表单,因此无法使用 Html 帮助程序。用户只需按下“重置截止日期”按钮。

对象上的“N”属性是它们的键。它是给定日期在一年中的天数,这意味着 1 月 16 日将是 N = 16。由于截止日期仅为 1 年,因此 N 值不会冲突,因此应该能够用作键。

我怎样才能成功地将这些条目保存在数据库中?我已经注释掉了 db.remove 方法,只是为了让添加条目起作用。我也尝试将条目状态设置为添加,但这也不起作用。我尝试调试并确认对象的所有属性都已正确初始化。

完全例外:

[OptimisticConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.]
   System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.ValidateRowsAffected(Int64 rowsAffected, UpdateCommand source) +142
   System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() +525
   System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction(Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) +453
   System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction) +252
   System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Func`1 operation) +206
   System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction) +270
   System.Data.Entity.Internal.InternalContext.SaveChanges() +145

[DbUpdateConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.]
   System.Data.Entity.Internal.InternalContext.SaveChanges() +280
   MyProject.Models.Services.DeadlinesService.ResetDeadlines() in \\PROJECTPATH\Models\Services\DeadlinesService.cs:49
   MyProject.Controllers.AdminController.ResetDeadlines() in \\PROJECTPATH\Controllers\AdminController.cs:254
   lambda_method(Closure , ControllerBase , Object[] ) +87
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +35
   System.Web.Mvc.Async.<>c.<BeginInvokeSynchronousActionMethod>b__9_0(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +39
   System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +77
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +42
   System.Web.Mvc.Async.<>c__DisplayClass11_0.<InvokeActionMethodFilterAsynchronouslyRecursive>b__0() +80
   System.Web.Mvc.Async.<>c__DisplayClass11_2.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +387
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +42
   System.Web.Mvc.Async.<>c__DisplayClass3_6.<BeginInvokeAction>b__4() +50
   System.Web.Mvc.Async.<>c__DisplayClass3_1.<BeginInvokeAction>b__1(IAsyncResult asyncResult) +188
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38
   System.Web.Mvc.<>c.<BeginExecuteCore>b__152_1(IAsyncResult asyncResult, ExecuteCoreState innerState) +26
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +73
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
   System.Web.Mvc.<>c.<BeginProcessRequest>b__20_1(IAsyncResult asyncResult, ProcessRequestState innerState) +40
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +73
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +602
   System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +195
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +128

编辑: 控制器动作:

public ActionResult ResetDeadlines()
        {
            deadlinesService.ResetDeadlines();

            return RedirectToAction("IndexDeadlines");
        }

查看:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <div class="row" style="margin-left:0px">
            <div>
                <label for="SearchInput" style="font-size:18px">@Res.Search @Res.Week</label>
                @Html.Editor("Search", new { htmlAttributes = new { @class = "form-control", @autofocus = "autofocus", @id = "SearchInput", @onkeyup = "myFunction()" } })
            </div>
            <div style="margin-left:10px;margin-top:18px">
                <a href="@Url.Action("ResetDeadlines")" class="customBtnXSmall">Reset Deadlines</a>
            </div>
        </div>
    </div>
}

这是截止日期类:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace MyProject.Models.DBModels
{
    public class Canteen_Deadlines
    {
        [Key]
        public long? N { get; set; } //Number of days into the year (16th of January is 16 days into the year, so N would be = 16)
        [Column(TypeName = "smalldatetime")]
        public DateTime? DeadlineDate { get; set; }
        public byte? WeekNo { get; set; }
        public byte? MonthNo { get; set; }
        public byte? QuarterNo { get; set; }
        public short YearNo { get; set; }
        public byte? DayofWeek { get; set; }
        public bool? LastDowInMonth { get; set; } //Last DayOfWeek In Month
        public byte? DoWAsc { get; set; } //DayOfWeek Ascending
    }
}

【问题讨论】:

    标签: c# asp.net .net asp.net-mvc entity-framework


    【解决方案1】:

    尝试使用此代码:

    .....
    
    var deadlines=new List<PP_CanteenScreen_Deadlines>();
    
    for (var i = 1; i < 53; i++)
     {
                    if (i == 1)
                        year += 1;
                    else
                        year = DateTime.Now.Year;
    
                    deadlineDate = GetThursdayOfWeek(year, i).AddDays(-7); //Gets the thursday 
                  //of the week before, because that is the deadline for that week.
                    weekOfMonth = monthOfLastWeek < deadlineDate.Month ? 1 : weekOfMonth + 1;
    
                    var newDeadline = new PP_CanteenScreen_Deadlines
                    {
                        N = DaysFromNewYear(year, deadlineDate),
                        DeadlineDate = deadlineDate,
                        WeekNo = (byte)i,
                        MonthNo = (byte)deadlineDate.Month,
                        QuarterNo = (byte)GetQuarterNumber(deadlineDate.Month),
                        YearNo = (short)year,
                        DayofWeek = 4,
                        LastDowInMonth = IsLastDoWInMonth(deadlineDate),
                        DoWAsc = (byte)weekOfMonth
                    };
                    deadlines.Add(newDeadline);
                   monthOfLastWeek = deadlineDate.Month;
    
    }
                    db.PP_CanteenScreen_Deadlines.AddRange(deadlines);
                   var result=  db.SaveChanges();
                  if(result < 52) .....your error code
    
    ........
    
    

    我想知道为什么你不尝试使用自动增量主键而不是 公长? N ?特别是我不喜欢您的主键可以为空。这有什么原因吗?

    【讨论】:

    • 我在“var result = db.SaveChanges();”处遇到了同样的异常不幸的是,使用您的代码。
    • 你能说明如何在 \\PROJECTPATH\Controllers\AdminController.cs:254 代码中调用 CanteenBIGScreen.Controllers.AdminController.ResetDeadlines() 吗?如果可能的话,整个行动。
    • 我已经添加了控制器操作和查看页面代码 - 我希望这是您想要看到的。
    • @Aletho 谢谢,但我想知道这是干什么用的:Html.Editor("Search", new { htmlAttributes = new { class= "form-control", autofocus = "autofocus", id = "搜索输入", onkeyup = "myFunction()" } })。我的意思是 myFunction?
    • 你能展示一下 PP_CanteenScreen_Deadline 类吗?它有父类吗?
    【解决方案2】:

    在多次尝试找出真正的问题并在@Sergey 的大力帮助下,我意识到根本问题是由于数据库中表的设计和 Entity Framework 6 的工作方式造成的。

    解决方案:

    我在我的代码中为Canteen_Deadlines 类添加了一个属性ID,它现在是关键,并在数据库表设计器中添加了一个相应的列。 EF6 现在知道我正在添加新行并让数据库表分配 ID,因此我可以分配自己的 N 个值。

    背景:

    EF6 一直表现得好像我在尝试更新我的行,因为 N 是我在 EF6 中的键,如果不是因为我正在尝试添加行,这将是有意义的。使用 Microsoft 文档在 UpdateConcurrencyException 上执行 Try-Catch 确认它正在尝试更新行,但是当我实际添加它们时无法执行(新异常是说 catch 逻辑不适用于实体处于“添加”状态)。

    【讨论】:

      猜你喜欢
      • 2015-02-17
      • 1970-01-01
      • 1970-01-01
      • 2016-05-19
      • 2018-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多