实体框架 - 尝试在创建新对象时插入空值

时间:2011-07-15 09:01:26

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

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

首先让我描述一下DB的结构。它是一个事件管理系统,其中每个事件都需要与练习组相关联,存储在缓存表中,但最终从Active Directory中获取。我手动创建了连接表 - 这是一个问题吗?无论如何,所以Event有一个指向EventPracticeGroup的外键,它有一个指向PracticeGroupCache的外键。 PracticeGroupCache还有一个指向Regions表的RegionId。

尝试插入新的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插入列'Name',表'XXXX.dbo.Regions';列不允许空值。 INSERT失败。声明已经终止。

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

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

请任何人都可以帮忙。在这一点上,只要有效,我就会决定使用最脏的解决方法。

此致 乔纳森。

3 个答案:

答案 0 :(得分:0)

看看你拨打这一行时会发生什么:

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);

BTW作为旁注:关于这个EventRepository.Repository.UnitOfWork.Context.XXX,请看看Ladislav Mrnka的回答:EF 4.0 IsAttachedTo extension method and error An object with the same key already exists

答案 1 :(得分:0)

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

在您的ID字段中,例如:

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

答案 2 :(得分:-1)

好像你已经找到了问题和解决方案。在您的数据库架构中,似乎列不允许NULL值。因此,要么将所有这些列更改为允许NULL,要么不插入null(这是您当前正在尝试执行的操作)