我遇到的问题与你们中的一些人一样 - 在尝试插入新对象时,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请求共享的。
请任何人都可以帮忙。在这一点上,只要有效,我就会决定使用最脏的解决方法。
此致 乔纳森。
答案 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
属性,因此其他字符串属性(例如Name
或Description
)为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(这是您当前正在尝试执行的操作)