实体框架代码第一次更新不会更新外键

时间:2011-10-11 15:38:19

标签: entity-framework-4.1 ef-code-first

我正在使用EF 4.1 Code First。我有一个实体,用这样的属性定义:

public class Publication 
{
    // other stuff
    public virtual MailoutTemplate Template { get; set; }
}

我使用流畅的样式配置了这个外键:

    modelBuilder.Entity<Publication>()
        .HasOptional(p => p.Template)
        .WithMany()
        .Map(p => p.MapKey("MailoutTemplateID"));

我有一个MVC表单处理程序,其中包含一些代码如下:

public void Handle(PublicationEditViewModel publicationEditViewModel)
        {
            Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
            publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
            if (publication.Id == 0)
            {
                _publicationRepository.Add(publication);
            }
            else
            {
                _publicationRepository.Update(publication);
            }
            _unitOfWork.Commit();
        }

在这种情况下,我们正在更新现有的Publication实体,因此我们将通过else路径。当_unitOfWork.Commit()触发时,UPDATE将发送到我在SQL事件探查器和Intellitrace中可以看到的数据库,但它不会在更新中包含MailoutTemplateID。

让它真正更新模板的诀窍是什么?

存储库代码:

public virtual void Update(TEntity entity)
{
    _dataContext.Entry(entity).State = EntityState.Modified;
}

public virtual TEntity Get(int id)
{
    return _dbSet.Find(id);
}

UnitOfWork代码:

public void Commit()
{
    _dbContext.SaveChanges();
}

2 个答案:

答案 0 :(得分:1)

取决于您的存储库代码。 :)如果您在上下文跟踪发布时设置publication.Template,我希望它能够正常工作。当您断开连接然后附加(具有导航属性但没有显式FK属性的场景)时,我猜测上下文没有足够的信息来计算调用SaveChanges时的详细信息。我做了一些实验。 1)进行集成测试,查询pub并将其附加到上下文,然后添加模板,然后保存。 2)在Publicaction类上粘贴一个MailOutTemplateId属性,看它是否有效。不建议#2作为解决方案,只是作为一种行为方式。我很想做这个实验,但还有其他一些我需要做的工作。;)

答案 1 :(得分:0)

我找到了让它发挥作用的方法。我最初不想做Get()(除了额外的数据库命中)的原因是我不能用AutoMapper魔法来获取这些值:

Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);

但是,我找到了另一种方法来做同样的事情而不使用返回值,所以我更新了我的方法,这样就可以了:

    public void Handle(PublicationEditViewModel publicationEditViewModel)
        {
            Publication publication = _publicationRepository.Get(publicationEditViewModel.Id);
            _mappingEngine.Map(publicationEditViewModel, publication);
//            publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
            publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
            if (publication.Id == 0)
            {
                _publicationRepository.Add(publication);
            }
            else
            {
                _publicationRepository.Update(publication);
            }
            _unitOfWork.Commit();
        }

我现在正在将一个IMappingEngine注入到类中,并通过StructureMap将其连接起来,如下所示:

    For<IMappingEngine>().Use(() => Mapper.Engine);

有关详情,请查看Jimmy's AutoMapper and IOC post