【问题标题】:Entity Framework - trying to insert null values when creating a new object实体框架 - 在创建新对象时尝试插入空值
【发布时间】:2011-07-15 09:01:25
【问题描述】:

我遇到了与你们中的一些人相同的问题 - 尝试插入新对象时,EF 为其某些属性插入空值,并且插入失败。

首先让我描述一下我们数据库的结构。它是一个事件管理系统,其中每个事件都需要与一个实践组相关联,存储在缓存表中,但最终从 Active Directory 中获取。我手动创建了连接表 - 有问题吗?反正Event有一个外键指向EventPracticeGroup,EventPracticeGroup有一个外键指向PracticeGroupCache。 PracticeGroupCache 还有一个 RegionId 指向 Regions 表。

在尝试插入新的 EventPracticeGroup 对象时出现问题。以下是我目前正在使用的代码:

var eventPracticeGroup = new EventPracticeGroup();
if (TryUpdateModel<EventPracticeGroup>(eventPracticeGroup))
{
    /*
    var eventId = EventScheduleRepository.GetById(Convert.ToInt32(Request.QueryString["EventScheduleId"])).EventId;
    eventPracticeGroup.Event = EventRepository.GetById(eventId);
    eventPracticeGroup.PracticeGroupCache = PracticeGroupCacheRepository.GetById(eventPracticeGroup.PracticeGroupCacheId);
    eventPracticeGroup.PracticeGroupCache.Region = RegionRepository.GetById(eventPracticeGroup.PracticeGroupCache.RegionId);
    EventPracticeGroupRepository.Add(eventPracticeGroup);
    */

    var eventId = EventScheduleRepository.GetById(Convert.ToInt32(Request.QueryString["EventScheduleId"])).EventId;
    var theEvent = new Event() { Id = eventId };
    EventRepository.Repository.UnitOfWork.Context.AttachTo("Events",theEvent);
    var practiceGroupCache = new PracticeGroupCache() { Id = eventPracticeGroup.PracticeGroupCacheId };
    practiceGroupCache.Region = new Region() { Id = eventPracticeGroup.PracticeGroupCache.RegionId };
    eventPracticeGroup.PracticeGroupCache = practiceGroupCache;
    EventPracticeGroupRepository.Add(eventPracticeGroup);
    EventPracticeGroupRepository.Save();
    return RedirectToAction("Index");
}

无论如何...如您所见,我刚刚尝试使用存根对象(没有帮助),并且我也尝试过实际获取和设置对象。我得到的错误是:

无法将值 NULL 插入“名称”列、表“XXXX.dbo.Regions”;列不允许空值。插入失败。该语句已终止。

显然名称不是关键字段。我检查了 EDMX XML - 只有 Id(主键列)将 StoreGeneratedPattern 设置为 Identity,因为它们应该(它们是 int32 标识列)。没有一个外键将 StoreGeneratedPattern 设置为标识。

如果我将 Regions.Name 设置为允许空值,则 PracticeGroupCaches.Description 会引发相同的错误。似乎每个链接对象都设置为空。我确实看过调试器,当我使用现在注释掉的代码时,没有什么是空的,一切都有一个值。我什至让 RegionRepository 返回所有区域,只是为了查看其中一个区域是否有一个空名称。没有。我的测试数据库中只有 2 个。我们的对象上下文是每个 HTTP 请求共享的。

请任何人帮忙。在这一点上,只要可行,我就会满足于使用最肮脏的解决方法。

问候, 乔纳森。

【问题讨论】:

    标签: entity-framework asp.net-mvc-2


    【解决方案1】:

    看看当你调用这行代码时会发生什么:

    EventPracticeGroupRepository.Add(eventPracticeGroup);
    

    您正在向上下文添加一个新的eventPracticeGroup。但eventPracticeGroup 有其他相关对象:

    eventPracticeGroup -> PracticeGroupCache -> Region
    

    然后您为这些对象创建新对象:

    var practiceGroupCache = new PracticeGroupCache() {
        Id = eventPracticeGroup.PracticeGroupCacheId };
    practiceGroupCache.Region = new Region() {
        Id = eventPracticeGroup.PracticeGroupCache.RegionId };
    eventPracticeGroup.PracticeGroupCache = practiceGroupCache;
    

    当您将eventPracticeGroup 添加到上下文时,整个对象图将被添加,这意味着 EF 将所有三个对象视为必须添加到数据库中的新对象。由于您只填写了Id 属性,因此其他字符串属性(如NameDescription)为null。因为它们在数据库中不可为空,所以 INSERT 命令失败。

    但我想您无论如何都不想将相关实体插入数据库,而只想插入eventPracticeGroup。因此,您需要在添加新对象之前将它们附加到上下文中,例如:

    var practiceGroupCache = new PracticeGroupCache() {
        Id = eventPracticeGroup.PracticeGroupCacheId };
    
    EventRepository.Repository.UnitOfWork.Context.AttachTo(
       "PracticeGroupCaches",practiceGroupCache);
    
    practiceGroupCache.Region = new Region() {
        Id = eventPracticeGroup.PracticeGroupCache.RegionId };
    
    EventRepository.Repository.UnitOfWork.Context.AttachTo(
       "Regions",practiceGroupCache.Region);
    
    eventPracticeGroup.PracticeGroupCache = practiceGroupCache;
    
    EventPracticeGroupRepository.Add(eventPracticeGroup);
    

    顺便说一句:关于这个EventRepository.Repository.UnitOfWork.Context.XXX 在这里看看Ladislav Mrnka 的回答:EF 4.0 IsAttachedTo extension method and error An object with the same key already exists

    【讨论】:

    • 谢谢,那里有一些有趣的注释,我会通读这些链接。即使我从存储库中获取对象(即上下文知道它们已经存在于数据存储中),它也会以同样的原因失败。如上所述,解决方案原来是将导航属性设置为null,然后分配一个EntityKey。感谢您的帮助!
    【解决方案2】:

    尝试添加:[DatabaseGenerated(DatabaseGeneratedOption.None)]

    在您的 ID 字段中,喜欢:

    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    

    【讨论】:

      【解决方案3】:

      您似乎已经找到了问题和解决方案。在您的数据库架构中,这些列似乎不允许 NULL 值。因此,要么更改所有这些列以允许 NULL,要么不插入 null(这是您目前正在尝试做的)

      【讨论】:

      猜你喜欢
      • 2019-05-22
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      • 1970-01-01
      相关资源
      最近更新 更多