RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1592831
Accepted
Chaos_Sower
Chaos_Sower
Asked:2024-09-04 20:41:39 +0000 UTC2024-09-04 20:41:39 +0000 UTC 2024-09-04 20:41:39 +0000 UTC

尝试通过实体框架操作数据时抛出异常

  • 772

有一个数据上下文类ApplicationContext.cs:

internal class ApplicationContext : DbContext
{
    public DbSet<Contact>? Contacts { get; set; }
    
    public DbSet<PhoneType>? PhoneTypes { get; set; }
    
    public DbSet<ContactInfo>? ContactsInfo { get; set; }
    
    public ApplicationContext() : base("Data Source=XXX;Initial Catalog=ContactsNotebookDB;Integrated Security=True;TrustServerCertificate=True")
    {
        Database.CreateIfNotExists();
    }
}

记录详情:

Contact.cs:

internal class Contact : IDatabase
{
    public required int ID { get; set; }
    
    public required string PhoneNumber { get; set; }
    
    public int? PhoneTypeID { get; set; }
    
    public required int ContactInfoID { get; set; }
}

ContactInfo.cs:

[Table("ContactsInfo")] // обязательное явное указание названия таблицы
(по умолчанию EF читает как "ContactInfoes")
internal class ContactInfo : IDatabase
{
    public required int ID { get; set; }
    
    public required string Name { get; set; }
    
    public required string Surname { get; set; }
    
    public string? Patronymic { get; set; }
    
    public required char Sex { get; set; }
}

当我尝试在其中之一的代码中保存数据View时,发生异常:

using ApplicationContext ApplicationContext = new();

int ContactsInfoMaxID = ApplicationContext.ContactsInfo.Count();
int ContactsMaxID = ApplicationContext.Contacts.Count();

ContactInfo ContactInfo = new()
{
    ID = ContactsInfoMaxID + 1,
    Name = NameTextBox.Text,
    Surname = SurnameTextBox.Text,
    Patronymic = Patronymic,
    Sex = SexComboBox.Text[0]
};

Contact Contact = new()
{
    ID = ContactsMaxID + 1,
    PhoneNumber = PhoneNumberTextBox.Text,
    PhoneTypeID = PhoneTypeComboBox.SelectedIndex,
    ContactInfoID = ContactInfo.ID,
};

ApplicationContext.ContactsInfo.Add(ContactInfo);
ApplicationContext.Contacts.Add(Contact);

ApplicationContext.SaveChanges(); // тут возникает исключение при сохранении

尝试添加记录时出现异常

该行ApplicationContext.SaveChanges();抛出以下异常:

System.Data.Entity.Infrastructure.DbUpdateException: "An error occurred while updating the entries. See the inner exception for details."

还有 2 个内部异常:

UpdateException: An error occurred while updating the entries. See the inner exception for details.

SqlException: Не удалось вставить значение NULL в столбец "ID", таблицы "ContactsNotebookDB.dbo.Contacts"; в столбце запрещены значения NULL. Ошибка в INSERT.
Выполнение данной инструкции было прервано.

问题更新:

当您尝试从数据库中删除记录时,也会发生异常。

包含尝试删除数据ViewModel的方法的代码片段:

/// <summary>
/// Команда удаления контакта
/// </summary>
/// <param name="parameter"></param>
private void DeleteContact(object parameter)
{
    MessageBoxResult DeleteContactMessageBoxResult = MessageBox.Show($"Внимание, вы действительно хотите удалить следующий контакт:\n\n{PhoneNumber}\n{Surname} {Name}{(Patronymic == "—" ? null : " " + Patronymic)}?", "Удаление контакта", MessageBoxButton.YesNo, MessageBoxImage.Warning);
    
    if (DeleteContactMessageBoxResult == MessageBoxResult.Yes)
    {
        using ApplicationContext ApplicationContext = new();
        
        bool IsContactInUse = ApplicationContext.Contacts.Any(Contact => Contact.ContactInfoID == ID);
        
        if (!IsContactInUse)
        {
            ApplicationContext.ContactsInfo?.Remove(ContactInfo);
        }
        
        else
        {
            Console.WriteLine("Текущий используется в Contact и не может быть удален.");
        }
        
        ApplicationContext.Contacts?.Remove(Contact);
        ApplicationContext.SaveChanges();
    }
}

尝试删除条目时出现异常

该行ApplicationContext.Contacts?.Remove(Contact);抛出异常:

System.InvalidOperationException: "The object cannot be deleted because it was not found in the ObjectStateManager."

附加信息:

  1. 版本Entity Framework- 6.5.1;
  2. 我对数据库条目的正确性充满信心,因为在通过调试进行检查期间,条目的目的是ApplicationContext: 向 ContactsInfo 添加条目

向联系人添加条目

已经很奇怪的是,ContactsInfo它只返回 1 条新记录,而Contacts它返回所有记录 + 一条新记录(顺便说一下,由于某种原因它被放置在表的顶部)。

即使我显式设置Null-данные,该条目仍然不会输入数据库,显示相同的异常。

PS我在添加的条目Contacts(属性PhoneTypeID)中看到0,我将其更正为1,但这并没有影响错误。

  1. debug 中的表达式ApplicationContext.ContactsInfo.Sql返回值:

    SELECT [范围 1].[ID] AS [ID]、[范围 1].[名称] AS [名称]、[范围 1].[姓氏] AS [姓氏]、[范围 1].[父名] AS [父名] FROM [ dbo].[联系人信息] AS [范围 1]

Sex也就是说,由于某种原因,数据库表中缺少一列。

  1. 我重新创建了数据库,创建了一个没有记录、没有关系的重复数据库,它没有主键和必填字段,但在这种情况下会引发另一个异常:

    System.Data.Entity.Infrastruct.DbUpdateConcurrencyException:“存储更新、插入或删除语句影响了意外数量的行 (0)。自加载实体以来,实体可能已被修改或删除。请参阅http://go.microsoft。 com/fwlink/?LinkId=472540了解有关理解和处理乐观并发异常的信息。”

和内部:

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.
  1. MS SQL 数据库中的表结构:

ContactsInfo:

ContactsInfo 表项目

Contacts:

联系人表项目

  1. 如果您尝试添加条目而不是添加到Contacts,而是添加到ContactsInfo并尝试保存更改,则会发生相同的异常,但具有不同的内部异常:

    SqlException:无法将 NULL 值插入表“ContactsNotebookDB.dbo.ContactsInfo”的列“Sex”;列中不允许有 NULL 值。插入错误。该指令被中止。

  2. 而且,好吧,从显而易见的角度来看,它当然ApplicationContext从数据库接收数据,因为它在访问它时返回正确的值(表及其记录的数量),所以问题不在于连接。

更新:

  1. 目前尚不清楚为什么该行ApplicationContext.Contacts?.Remove(Contact);会导致异常,因为联系人数据库中的数据已加载到ApplicationContext(尽管调试中的检查工作正常:它要么显示已加载Contacts,要么写入其编号为 0)。
c#
  • 1 1 个回答
  • 90 Views

1 个回答

  • Voted
  1. Best Answer
    Chaos_Sower
    2024-09-07T07:14:30Z2024-09-07T07:14:30Z

    @Alexander Petrov在评论中的建议:

    简而言之,删除 int ContactsInfoMaxID = ApplicationContext.ContactsInfo.Count(); 行int ContactsMaxID = ApplicationContext.Contacts.Count();。删除 ID = ContactsInfoMaxID + 1 和 ID = ContactsMaxID + 1(保留 ID 未初始化,数据库将自行设置它们)。

    正中目标!但我将此作为建议,但我从未想过这是解决这个问题的唯一方法。顺便说一句,当我第一次使用它时,由于某种原因我无法解决问题。

    奇怪的是,我将从修复从数据库中删除记录的功能开始,因为它更容易。

    为此,您只需在使用 删除之前使用 方法附加要删除的记录。Attach()Remove()

    例如:

    ApplicationContext.Contacts.Attach(Contact); // прикрепляем удаляемый объект к контексту
    ApplicationContext.Contacts.Remove(Contact);
    await ApplicationContext.SaveChangesAsync();
    

    但Attach()只有在以下情况下才需要:

    • 该对象是从另一个源获取的(例如,从缓存、从前端或另一个上下文);
    • 该对象是手动创建的,需要在数据库中删除或更新。

    也就是说,如果该对象是通过当前上下文(通过Find、FirstOrDefault等方法)从数据库获取的,那么在这种情况下该对象已被跟踪,并且不需要LINQ-запросы使用该方法。Attach()

    就这样。这足以删除条目。并且没有像将主键更改为自动递增键那样“敲着手鼓跳舞”。我并不是说自动递增键不好。我只是说Remove()至少提供了选择的自由。

    我会立即说答案是从这里获取的:https://stackoverflow.com/questions/7791149/the-object-cannot-be-deleted-because-it-was-not-found-in-the-对象状态管理器。

    Add()使用...方法向数据库添加记录则不能说同样的情况。

    为了能够在数据库中创建新条目,您需要......不,不是更改代码,而是更改数据库中的体系结构。

    即向key指示ID它是自增的。就这样!

    即在表project中,修改MS SQL字段参数ID如下:

    ID 字段自动递增选项

    代码的最终版本:

    ContactInfo ContactInfo = new()
    {
        Name = NameTextBox.Text,
        Surname = SurnameTextBox.Text,
        Patronymic = Patronymic,
        Sex = SexComboBox.Text/*[0]*/
    };
    
    Contact Contact = new()
    {
        PhoneNumber = PhoneNumberTextBox.Text,
        PhoneTypeID = PhoneTypeID,
        ContactInfoID = ContactInfo.ID
    };
    
    using ApplicationContext ApplicationContext = new();
    
    if (ContactViewModel != null) // если редактируем запись
    {
        Contact? DBContact = ApplicationContext.Contacts?.FirstOrDefault(Contact => Contact.ID == ContactViewModel.ID);
        ContactInfo? DBContactInfo = ApplicationContext.ContactsInfo?.FirstOrDefault(Contact => Contact.ID == ContactViewModel.ContactInfo.ID);
        
        if (DBContactInfo != null)
        {
            DBContactInfo.Name = ContactInfo.Name;
            DBContactInfo.Surname = ContactInfo.Surname;
            DBContactInfo.Patronymic = ContactInfo.Patronymic;
            DBContactInfo.Sex = ContactInfo.Sex;
        }
        
        if (DBContact != null)
        {
            DBContact.PhoneNumber = Contact.PhoneNumber;
            DBContact.PhoneTypeID = Contact.PhoneTypeID;
        }
    }
    
    else // если создаём новую запись
    {
        ApplicationContext.ContactsInfo?.Add(ContactInfo);
        await ApplicationContext.SaveChangesAsync();
        
        Contact.ContactInfoID = ContactInfo.ID;
        ApplicationContext.Contacts?.Add(Contact);
    }
    
    await ApplicationContext.SaveChangesAsync();
    

    更新: 重要!请注意,如果您有一个从属实体(在本例中,我有一个依赖于 y 的属性 ContactInfoIDy),那么在将新记录添加到数据库之前,您需要一一保存实体:ContactIDContactInfo

    ApplicationContext.ContactsInfo?.Add(ContactInfo);
    await ApplicationContext.SaveChangesAsync();
    
    Contact.ContactInfoID = ContactInfo.ID;
    ApplicationContext.Contacts?.Add(Contact);
    await ApplicationContext.SaveChangesAsync();
    

    因为在初始化时IDy 是ContactInfo相等的0-ID 只有在添加到数据库后才会对其进行赋值!如果在数据库中设置了外键限制,这一点尤其明显:

    初始化时 ContactInfo.Id = 0

    外键约束异常

    • 1

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5