I have 3 tables with relationship to the same TransactionLog.DocumentId column. I differentiate the Foreign Key with DocumentTypeId:
1 - Invoice, 2 - DebitNote, 3 - CreditNote
I scaffold the entities:
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; }
}
I want to insert 1 record to each of the table Invoice, DebitNote and CreditNote, and 3 records for each transaction to TransactionLog.
And this is my code:
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");
});
}
However, the DocumentId doesn't save the correct InvoiceId, CreditNoteId, DebitNoteId. I check with SQL Profiler, it will always get the first scope_identity() of the 3 inserts, which in my case is CreditNoteid.
Any idea how to get the correct Id from Invoice, CreditNote and DebitNote ? Or shouldn't I use relationship in this case. If not, what is the best practice of logging the transaction into the log?
Add the following configurations in your DbContext
and then add a migration and update the database accordingly.
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);
}
I think maybe the Foreign Key's direction is wrong.
As your table definition, the TransactionLog.DocumentId
's value must be exist in the three tables ( Invoice
CreditNote
DebitNote
) at the same time. So, if only insert two of them, there will maybe have a Exception.
I think you really want table definition is like this. I delete TransactionLog.DocumentId
column and add FKs from the PK of the three tables to TransactionLog.TransactionLogId
.
the entities:
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; }
}
code:
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);
I guess you have a wrong relationship there. like one transaction can have multiple invoices but an invoice will have only one transaction record. I might be wrong because sometimes it feels like one-to-one but anyways I gave it a try and here is what you want.
the entities:
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; }
}
and to insert data:
var invoice = new Invoice()
{
InvoiceNumber = "Inv099",
Amount = 66m,
InvoiceLog = new Collection<TransactionLog>()
{
new TransactionLog(){DocumentTypeId = 1, Amount = 66m}
}
};
var creditNote = new CreditNote()
{
CreditNoteNumber = "DN002",
Amount = 99.99m,
CreditLog = new Collection<TransactionLog>()
{
new TransactionLog(){DocumentTypeId = 3, Amount = 99.99m}
}
};
var debitNote = new DebitNote()
{
DebitNoteNumber = "CN008",
Amount = 77.77m,
DebitLog = new Collection<TransactionLog>()
{
new TransactionLog(){DocumentTypeId = 2, Amount = 77.77m}
}
};
using (var context = new TestMVCEntities())
{
context.Invoices.Add(invoice);
context.CreditNotes.Add(creditNote);
context.DebitNotes.Add(debitNote);
context.SaveChanges();
}
and the table will look like this:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.