将具有FK的实体添加到现有实体时的EF6 EntityValidationErrors(仅使用id)

时间:2014-05-05 19:10:26

标签: asp.net sql entity-framework repository-pattern

我有以下情况。

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string AppId { get; set; }
    public string Token { get; set; }
    public ICollection<Document> Documents { get; set; }
}


public class Document
{
    public int Id { get; set; }
    public string Name { get; set; }
    public byte[] PdfBinary { get; set; }
    public string PdfFileName { get; set; }
    public int SignersCount { get; set; }
    public int CompanyId { get; set; }
    public Company Company { get; set; }
    public int Pages { get; set; }

    public ICollection<TagDefinition> Tags { get; set; }

    public Document()
    {
        Company = new Entities.Company();
        Tags = new List<TagDefinition>();
    }
}

现在,这是

的映射器或配置文件
public class CompanyMapper: EntityTypeConfiguration<Company>
{
    public CompanyMapper()
    {
        this.ToTable("Companies");

        this.HasKey(c => c.Id);
        this.Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(c => c.Id).IsRequired();

        this.Property(c => c.Name).IsRequired();
        this.Property(c => c.AppId).IsRequired();
        this.Property(c => c.Token).IsRequired();
    }
}

 public class DocumentMapper: EntityTypeConfiguration<Document>
{
    public DocumentMapper()
    {
        this.ToTable("Documents");

        this.HasKey(c => c.Id);
        this.Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(c => c.Id).IsRequired();

        this.Property(c => c.Name).IsRequired();
        this.Property(c => c.Name).HasMaxLength(255);

        this.Property(c => c.Pages).IsOptional();

        this.Property(c => c.SignersCount).IsRequired();

        this.Property(c => c.PdfBinary).IsRequired();
        this.Property(c => c.PdfBinary).IsMaxLength();

        this.Property(c => c.PdfFileName).IsRequired();

        HasRequired(c => c.Company).WithMany(c => c.Documents).HasForeignKey(c => c.CompanyId);
    }
}

这就是问题所在。 (见下面的解释代码)

我想创建一个新文档...所以,当我尝试将新文档添加到我的数据库并且只设置CompanyId(而不是整个公司实例)时,我收到以下错误...

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

当我查看GetValidationErrors()集合时,它基本上告诉我公司的字段是空的(它们在dabatase中被标记为必需)。因此,似乎正在尝试为公司ID = 1创建一个新记录......这很奇怪,因为它已经存在。我对这款EF6如何工作感到困惑。我的理解是,通过在我的Document对象中设置ComapanyId属性,然后使用配置文件映射它,足以使INSERT按预期工作。现在,如果我传递给整个公司实体的文件,那么它按预期工作。

是否公司有足够的信息让EF知道它属于公司表中id = 1的记录?

var doc = new Document(){ Name = "Name",
        PdfFileName = "Filename",
        CompanyId = 1};
        _repo.Create(doc);

这是存储库...

public abstract class WriteRepository<TContext> : IWriteRepository where TContext : DbContext, new()
{
    private readonly TContext _context;

    protected TContext Context { get { return _context; } }

    protected WriteRepository()
    {
        _context = new TContext();
    }

    public void Dispose()
    {
        _context.Dispose();
    }

    ...

    public TItem Create<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new()
    {
        return PerformAction(item, EntityState.Added, saveImmediately);
    }

    protected virtual TItem PerformAction<TItem>(TItem item, EntityState entityState, bool saveImmediately = true) where TItem : class, new()
    {
        _context.Entry(item).State = entityState;
        if (saveImmediately)
        {
            try
            {
                _context.SaveChanges();
            }
            catch (Exception ex)
            {
                var x = _context.GetValidationErrors();
            }
        }
        return item;
    }

对我来说很奇怪,如果我有一个FK的有效ID,我仍然必须将整个Company实例传递给文档实例。我试图找到有关它的文档。我发现类似于我的例子似乎适合他们,但不适合我:(

提前谢谢你......

1 个答案:

答案 0 :(得分:0)

首先,您不必设置自己的EntityState。如果您正确地建立关系模型,EF应该为您跟踪。

您最好的选择是将公司视为总路线。然后让它处理建立关系。这样的事情将是一个很好的起点:

var company = companySet.FirstOrDefault(x => x.Id == 1);

var newDoc = new Document()
{                
    Name = "foo doc",
    Pages = 1,
    SignersCount = 0,
    PdfBinary = new byte[]{},
    PdfFileName = "foo.pdf"
};

company.AddDocument(newDoc);

然后在公司课上:

public void AddDocument(Document document)
{
    document.Company = this;
    Documents.Add(document);
}

此处的关键是您需要将文档添加到公司文档集合中以正确保存关系数据。

然后你只需要在你的DbContext上调用SaveChanges。你如何做到这一点取决于你。您可能需要稍微使用您的存储库设计。

希望这有帮助。