【问题标题】:EF core inserts new record instead of updatingEF核心插入新记录而不是更新
【发布时间】:2020-04-23 14:09:26
【问题描述】:

我搜索了相关问题,但找不到解决方案。我有一个 asp.net 核心网络应用程序,我在其中选择一行并编辑记录。它在带有相关数据的弹出窗口中显示表单,ID 也是(隐藏的)。这是实体:

public class Sender
{
    public long Id { get; set; }
    public string  Name { get; set; }
    public string Address { get; set; }
    public string ContactPerson { get; set; }
    public string ContactEmail { get; set; }
    public IEnumerable<Document> Documents { get; set; }
}

我使用存储库模式来处理数据操作:

public class DataSender : IRepositorySender
{
    private DataContext DataContext;
    public DataSender(DataContext Context)
    {
        DataContext = Context;
    }
    public IEnumerable<Sender> Senders => DataContext.Senders;
    public Sender GetSender(long SenderId)
    {
        return DataContext.Senders.Find(SenderId);
    }
    public void AddSender(Sender Sender)
    {
        DataContext.Senders.Add(Sender);
        DataContext.SaveChanges();
    }
    public void UpdateSender(Sender Sender)
    {
        DataContext.Senders.Update(Sender);
        DataContext.SaveChanges();
    }
    public void DeleteSender(Sender Sender)
    {

    }
}

这是相关的操作:

[Route("{SenderId}")]
    public IActionResult UpdateSender(long SenderId)
    {
        ViewBag.Mode = "update";
        return PartialView("Sender", SenderRepository.GetSender(SenderId));
    }
    [HttpPost("UpdateSender")]
    public IActionResult UpdateSender(Sender Sender)
    {
        SenderRepository.UpdateSender(Sender);
        return RedirectToAction(nameof(List));
    }

我在弹出窗口中获得了所需的数据,保存了更改,但 EF 插入了一条新记录而不是更新它。为什么?

编辑:

这是更新视图:

@model Sender

<form asp-action=@(ViewBag.Mode == "new" ? "AddSender" : "UpdateSender") asp-controller="Sender"  method="post">
    @using (Html.DevExtreme().ValidationGroup())
    {
        @(Html.DevExtreme().Form<Sender>()
            .ID("form")
            .ColCount(1)
            .Items(items => {
            items.AddSimpleFor(m => Model.Id).Visible(false);
            items.AddSimpleFor(m => Model.Name);
            items.AddSimpleFor(m => Model.Address);
            items.AddSimpleFor(m => Model.ContactPerson);
            items.AddSimpleFor(m => Model.ContactEmail);
            items.AddGroup().Items(groupItem => groupItem.AddSimple().Template(
                @<text>
                    <div style="text-align: right">
                        @(Html.DevExtreme().Button().ID("save").Text("Mentés").Width(100).Type(ButtonType.Success).UseSubmitBehavior(true))
                        @(Html.DevExtreme().Button().ID("cancel").Text("Mégsem").Width(100).Type(ButtonType.Normal).OnClick("close_onClick"))
                    </div>

                </text>));
            })
            .LabelLocation(FormLabelLocation.Top)
            .FormData(Model)
        )
    }
</form>

编辑 2: 这是调试窗口的输出。对你有用吗?我明白了,EF 需要一个新的 Id 并将记录插入数据库中。关键是,为什么 Id 为 0,为什么 EF 或 webapp(模型绑定)不识别,实体已经有一个有效的 Id 值。

Microsoft.EntityFrameworkCore.ChangeTracking: Debug: 'DataContext' generated temporary value '-9223372036854774805' for the 'Id' property of new 'Sender' entity.
Microsoft.EntityFrameworkCore.ChangeTracking: Debug: Context 'DataContext' started tracking 'Sender' entity with key '{Id: -9223372036854774805}'.
Microsoft.EntityFrameworkCore.ChangeTracking: Debug: DetectChanges starting for 'DataContext'.
Microsoft.EntityFrameworkCore.ChangeTracking: Debug: DetectChanges completed for 'DataContext'.
Microsoft.EntityFrameworkCore.Database.Transaction: Debug: Beginning transaction with isolation level 'Unspecified'.
Microsoft.EntityFrameworkCore.Database.Transaction: Debug: Began transaction with isolation level 'ReadCommitted'.
Microsoft.EntityFrameworkCore.Database.Command: Debug: Creating DbCommand for 'ExecuteReader'.
Microsoft.EntityFrameworkCore.Database.Command: Debug: Created DbCommand for 'ExecuteReader' (3ms).
Microsoft.EntityFrameworkCore.Database.Command: Debug: Executing DbCommand [Parameters=[@p0='Teszt cím' (Nullable = false) (Size = 4000), @p1='teszt@teszt.com' (Nullable = false) (Size = 4000), @p2='Teszt név' (Nullable = false) (Size = 4000), @p3='Teszt cég' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Senders] ([Address], [ContactEmail], [ContactPerson], [Name])
VALUES (@p0, @p1, @p2, @p3);
SELECT [Id]
FROM [Senders]
WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();
Microsoft.EntityFrameworkCore.ChangeTracking: Debug: Foreign key property 'Sender.Id' detected as changed from '-9223372036854774805' to '71' for entity with key '{Id: 71}'.
Microsoft.EntityFrameworkCore.Database.Command: Debug: A data reader was disposed.
Microsoft.EntityFrameworkCore.Database.Transaction: Debug: Committing transaction.
Microsoft.EntityFrameworkCore.Database.Transaction: Debug: Committing transaction.
Microsoft.EntityFrameworkCore.Database.Transaction: Debug: Disposing transaction.
Microsoft.EntityFrameworkCore.ChangeTracking: Debug: The 'Sender' entity with key '{Id: 71}' tracked by 'DataContext' changed from 'Added' to 'Unchanged'.

【问题讨论】:

  • 如果 Id 值已经存在,EF 将不会插入,您将得到 Cannot insert explicit value for identity column 异常,或者您在 SQL 中启用了身份插入
  • 我不想插入,我想更新。此评论与问题有何关联?
  • 实体框架会看到 Id 字段,如果它为 0,那么它将插入,否则它将更新
  • 正如我所写,我在隐藏字段中有对应的记录 ID。我更改了更新方法,现在我为每个字段分配了新值,现在我看到 Id 为 0。但是为什么呢?在弹出表单中,我看到了正确的 Id 值。
  • 分享您的视图和控制器动作,调试并检查您是否在控制器动作中收到 id 值

标签: asp.net-core entity-framework-core


【解决方案1】:

我明白了,没有看到完整的流程就忍不住了,你可以尝试使用 Debug Logger 并查看更改跟踪

 services.AddDbContext<ApplicationDbContext>(options => options
              .UseLoggerFactory(MyLoggerFactory)
              .UseSqlServer(Configuration.GetConnectionString("DefaultConnection")).EnableSensitiveDataLogging());
              
              
              
               public static readonly ILoggerFactory MyLoggerFactory
            = LoggerFactory.Create(builder =>
            {
                builder
                    .AddFilter((category, level) =>
                        (category == DbLoggerCategory.ChangeTracking.Name |
                         category == DbLoggerCategory.Database.Transaction.Name |
                         category == DbLoggerCategory.Database.Command.Name)
                         && level == LogLevel.Debug)
                    .AddDebug();
            });
            
            
            

这将生成调试日志,其中包含 Entityframework Core 发出的更改跟踪、事务和命令以及传递的数据,请特别注意更改跟踪,因为这将确定您的对象是否正在添加或更新

编辑1 调试:“DataContext”为新的“Id”属性生成临时值“-9223372036854774805”

我看到 Id 在您的控制器和 savechanges 之间的某些被删除的地方没有价值,您是否使用任何类型的映射,或者检查您的存储库,使用 f11 进行调试并查看它丢失的位置

【讨论】:

  • 我用调试窗口的输出编辑了帖子。
【解决方案2】:

问题是,Id 字段的可见性设置为 false,这导致默认值 0 和。不绑定 Id 字段。我添加了一个@Html.HiddenFor(m =&gt; Model.Id) 字段,现在它可以按预期工作了。

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 2014-05-18
    • 2020-07-19
    • 1970-01-01
    • 2014-12-16
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多