EF 0..1到多个关系更新

时间:2016-06-22 11:20:52

标签: c# sql-server entity-framework foreign-keys entity-framework-6

我无法理解这一点,所有的线索都是如此,我做了所有正确的事情,但显然我一定错过了什么......

鉴于这两个对象defs ......

public class Invoice
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("Block")]
    public int? BlockingCodeId { get; set; }

    public virtual BlockingCode Block { get; set; }

    ...

}

public class BlockingCode
{
    [Key]
    public int Id { get; set; }
    public virtual ICollection<Invoice> Invoices { get; set; }
    ...
}

然后使用适当的关系配置上下文......

public class FaureciaContext : EFDataContext
{
    public virtual DbSet<Invoice> Invoices { get; set; }
    public virtual DbSet<BlockingCode> BlockingCodes { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Invoice>()
            .HasOptional(e => e.Block)
            .WithMany(e => e.Invoices);
    }
}

为什么我这样做......

// assume this invoice has a BlockingCode relationship
var invoice = db.Invoices.First();
invoice.BlockingCodeId = null;
db.Savechanges();

我是否得到此异常......

  

操作失败:无法更改关系,因为   一个或多个外键属性是不可为空的。当一个   改变了关系,相关的外键属性是   设置为空值。如果外键不支持空值,   必须定义新的关系,外键属性必须是   分配了另一个非空值,或者不相关的对象必须是   删除。

编辑:

我想我会补充一下,因为这里的答案并没有真正指出我遇到的问题的真正答案......

事实证明,有问题的引用并不是我实际上更新了代码中的发票类的另一个子属性的问题....

invoice.Lines = MergLines(newVersion, dbVersion);

我的合并代码工作正常,但任何敏锐的EF用户都知道你不能简单地#34;替换子集合&#34;像这样,你必须删除旧的并根据需要添加新的。

1 个答案:

答案 0 :(得分:1)

因此,根据我的假设对此进行逆向工程是您正在使用的基本SQL表结构......

阻止表:

Block Table Definition

发票表:

Invoice Table Definition

并且在Invoice.BlockingCodeId和Block.Id之间定义了外键关系......

FK Relationship

当让EF从物理数据库创建它们时,我得到以下代码优先的实体类和上下文:

[Table("Block")]
public partial class Block
{
    public Block()
    {
        Invoices = new HashSet<Invoice>();
    }

    public int Id { get; set; }

    [Required]
    [StringLength(50)]
    public string Description { get; set; }

    public virtual ICollection<Invoice> Invoices { get; set; }
}

[Table("Invoice")]
public partial class Invoice
{
    public int Id { get; set; }

    public int? BlockingCodeId { get; set; }

    [Required]
    [StringLength(50)]
    public string Description { get; set; }

    public virtual Block Block { get; set; }
}

public partial class TestContext : DbContext
{
    public TestContext()
        : base("name=TestContext")
    {
    }

    public virtual DbSet<Block> Blocks { get; set; }
    public virtual DbSet<Invoice> Invoices { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Block>()
            .HasMany(e => e.Invoices)
            .WithOptional(e => e.Block)
            .HasForeignKey(e => e.BlockingCodeId);
    }
}

当如上配置实体和上下文时,以下代码执行时没有问题,我看到了我在SQL数据库中的期望:

var context = new TestContext();
var block = new Block { Description = "Block 1" };
var invoices = new List<Invoice>
                    {
                        new Invoice { Description = "Invoice 1" },
                        new Invoice { Description = "Invoice 2" }
                    };

invoices.ForEach(i => block.Invoices.Add(i));
context.Blocks.Add(block);
context.SaveChanges();

block = null;
var invoice = context.Invoices.First();
invoice.Block = null;
context.SaveChanges();

执行后,生成的数据状态为......

阻止表:

Block Data

发票表:

Invoice Data