在同一列上具有多个外键的实体框架核心

时间:2018-09-19 07:17:19

标签: c# sql-server entity-framework

我有3个表,它们与同一个TransactionLog.DocumentId列相关。 我用DocumentTypeId区分外键:

1-发票, 2-DebitNote, 3-CreditNote

enter image description here

我搭建实体的脚手架:

public partial class TransactionLog
{
    public int TransactionLogId { get; set; }
    public int? DocumentId { get; set; }
    public int? DocumentTypeId { get; set; }
    public decimal? Amount { get; set; }

    public CreditNote CreditNote { get; set; }
    public Invoice Invoice { get; set; }
    public DebitNote DebitNote { get; set; }
}

public partial class Invoice
{
    public Invoice()
    {
        TransactionLog = new HashSet<TransactionLog>();
    }

    public int InvoiceId { get; set; }
    public string InvoiceNumber { get; set; }
    public decimal Amount { get; set; }

    public ICollection<TransactionLog> TransactionLog { get; set; }
}

public partial class DebitNote
{
    public DebitNote()
    {
        TransactionLog = new HashSet<TransactionLog>();
    }

    public int DebitNoteId { get; set; }
    public string DebitNoteNumber { get; set; }
    public decimal Amount { get; set; }

    public ICollection<TransactionLog> TransactionLog { get; set; }
}

public partial class CreditNote
{
    public CreditNote()
    {
        TransactionLog = new HashSet<TransactionLog>();
    }

    public int CreditNoteId { get; set; }
    public string CreditNoteNumber { get; set; }
    public decimal Amount { get; set; }

    public ICollection<TransactionLog> TransactionLog { get; set; }
}

我想在每个表Invoice,DebitNote和CreditNote中插入1条记录,并为每笔交易向TransactionLog插入3条记录。

这是我的代码:

enter image description here

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        modelBuilder.Entity<CreditNote>(entity =>
        {
            entity.Property(e => e.Amount).HasColumnType("decimal(18, 4)");

            entity.Property(e => e.CreditNoteNumber)
                .HasMaxLength(50)
                .IsUnicode(false);
        });

        modelBuilder.Entity<DebitNote>(entity =>
        {
            entity.Property(e => e.Amount).HasColumnType("decimal(18, 4)");

            entity.Property(e => e.DebitNoteNumber)
                .HasMaxLength(50)
                .IsUnicode(false);
        });

        modelBuilder.Entity<Invoice>(entity =>
        {
            entity.Property(e => e.Amount).HasColumnType("decimal(18, 4)");

            entity.Property(e => e.InvoiceNumber)
                .HasMaxLength(50)
                .IsUnicode(false);
        });

        modelBuilder.Entity<TransactionLog>(entity =>
        {
            entity.Property(e => e.Amount).HasColumnType("decimal(18, 4)");

            entity.HasOne(d => d.CreditNote)
                .WithMany(p => p.TransactionLog)
                .HasForeignKey(d => d.DocumentId)
                .HasConstraintName("FK_TransactionLog_CreditNote");

            entity.HasOne(d => d.DebitNote)
                .WithMany(p => p.TransactionLog)
                .HasForeignKey(d => d.DocumentId)
                .HasConstraintName("FK_TransactionLog_DebitNote");

            entity.HasOne(d => d.Invoice)
                .WithMany(p => p.TransactionLog)
                .HasForeignKey(d => d.DocumentId)
                .HasConstraintName("FK_TransactionLog_Invoice");
        });
    }

但是,DocumentId没有保存正确的InvoiceId,CreditNoteId,DebitNoteId。我使用SQL事件探查器进行检查,它将始终获得3个插入的第一个scope_identity(),在我的情况下为CreditNoteid。

enter image description here

任何想法如何从Invoice,CreditNote和DebitNote获取正确的ID? 或者在这种情况下我不应该使用关系。 如果没有,将事务记录到日志中的最佳实践是什么?

3 个答案:

答案 0 :(得分:0)

DbContext中添加以下配置,然后添加迁移并相应地更新数据库。

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

    modelBuilder.Entity<Invoice>().HasMany(i => i.TransactionLog).WithOne(tl => tl.Invoice).HasForeignKey(tl => tl.DocumentId);
    modelBuilder.Entity<DebitNote>().HasMany(dn => dn.TransactionLog).WithOne(tl => tl.DebitNote).HasForeignKey(tl => tl.DocumentId);
    modelBuilder.Entity<CreditNote>().HasMany(cn => cn.TransactionLog).WithOne(tl => tl.CreditNote).HasForeignKey(tl => tl.DocumentId);
}

答案 1 :(得分:0)

我认为外键的方向可能是错误的。

作为表定义,TransactionLog.DocumentId的值必须同时存在于三个表(Invoice CreditNote DebitNote)中。因此,如果仅插入其中两个,则可能会有异常。

enter image description here

我认为您真的希望表定义是这样的。 我删除了TransactionLog.DocumentId列,并将三个表的PK中的FK添加到了TransactionLog.TransactionLogId

enter image description here

实体:

public partial class TransactionLog
{
    public int TransactionLogId { get; set; }
    public Nullable<int> DocumentTypeId { get; set; }
    public Nullable<decimal> Amount { get; set; }

    public virtual CreditNote CreditNote { get; set; }
    public virtual DebitNote DebitNote { get; set; }
    public virtual Invoice Invoice { get; set; }
}

public partial class Invoice
{
    public int InvoiceId { get; set; }
    public string InvoiceNumber { get; set; }
    public decimal Amount { get; set; }

    public virtual TransactionLog TransactionLog { get; set; }
}

public partial class CreditNote
{
    public int CreditNoteId { get; set; }
    public string CreditNoteNumber { get; set; }
    public decimal Amount { get; set; }

    public virtual TransactionLog TransactionLog { get; set; }
}

public partial class DebitNote
{
    public int DebitNoteId { get; set; }
    public string DebitNoteNumber { get; set; }
    public decimal Amount { get; set; }

    public virtual TransactionLog TransactionLog { get; set; }
}

代码:

Invoice invoice = new Invoice() { InvoiceNumber = "Inv0100", Amount = 66m };
TransactionLog invoiceLog = new TransactionLog() { Amount = invoice.Amount, DocumentTypeId = 1 };
invoice.TransactionLog = invoiceLog;
_context.Invoices.Add(invoice);

CreditNote creditNote = new CreditNote() { CreditNoteNumber = "DN003", Amount = 99.99m };
TransactionLog creditNoteLog = new TransactionLog() { Amount = creditNote.Amount, DocumentTypeId = 2 };
creditNote.TransactionLog = creditNoteLog;
_context.CreditNotes.Add(creditNote);

DebitNote debitNote = new DebitNote() { DebitNoteNumber = "CN009", Amount = 77.77m };
TransactionLog debitNoteLog = new TransactionLog() { Amount = debitNote.Amount, DocumentTypeId = 3 };
debitNote.TransactionLog = debitNoteLog;
_context.DebitNotes.Add(debitNote);

答案 2 :(得分:0)

我猜你那里的关系不对。例如一笔交易可以有多张发票,但是一张发票将只有一个交易记录。我可能是错的,因为有时候感觉就像一对一,但无论如何我还是尝试了一下,这就是您想要的。

实体:

mod.wizards.newContentElement.wizardItems.common.elements

并插入数据:

public class TestMVCEntities : DbContext
{

    public TestMVCEntities()
        : base("name=TestMVCEntities")
    {
    }

    public DbSet<Invoice> Invoices { get; set; }
    public DbSet<DebitNote> DebitNotes { get; set; }
    public DbSet<CreditNote> CreditNotes { get; set; }
    public DbSet<TransactionLog> TransactionLogs { get; set; }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TransactionLog>()
            .HasRequired(p => p.Invoice)
            .WithMany(p => p.InvoiceLog)
            .HasForeignKey(p => p.DocumentId);

        modelBuilder.Entity<TransactionLog>()
            .HasRequired(p => p.DebitNote)
            .WithMany(p => p.DebitLog)
            .HasForeignKey(p => p.DocumentId);

        modelBuilder.Entity<TransactionLog>()
            .HasRequired(p => p.CreditNote)
            .WithMany(p => p.CreditLog)
            .HasForeignKey(p => p.DocumentId);
    }
}

public partial class TransactionLog
{
    public int TransactionLogId { get; set; }
    public int? DocumentId { get; set; }
    public int? DocumentTypeId { get; set; }
    public decimal? Amount { get; set; }

    public CreditNote CreditNote { get; set; }
    public Invoice Invoice { get; set; }
    public DebitNote DebitNote { get; set; }
}

public partial class Invoice
{
    public int InvoiceId { get; set; }
    public string InvoiceNumber { get; set; }
    public decimal Amount { get; set; }

    public ICollection<TransactionLog> InvoiceLog { get; set; }
}

public partial class DebitNote
{
    public int DebitNoteId { get; set; }
    public string DebitNoteNumber { get; set; }
    public decimal Amount { get; set; }

    public ICollection<TransactionLog> DebitLog { get; set; }
}

public partial class CreditNote
{
    public int CreditNoteId { get; set; }
    public string CreditNoteNumber { get; set; }
    public decimal Amount { get; set; }

    public ICollection<TransactionLog> CreditLog { get; set; }
}  

,表格将如下所示:

enter image description here