Ядро Entity Framework с несколькими внешними ключами в одном столбце - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть 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; }
}

Я хочу вставить 1 запись в каждую из таблиц Invoice, DebitNote и CreditNote и 3 записи для каждой транзакции в TransactionLog.

И это мой код:

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 Profiler, он всегда получит первый scope_identity () из 3 вставок, в моем случае это CreditNoteid.

enter image description here

Любая идеяКак получить правильный идентификатор из счета-фактуры, CreditNote и DebitNote?Или я не должен использовать отношения в этом случае.Если нет, то как лучше записать транзакцию в журнал?

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Я думаю, что, возможно, направление внешнего ключа неверно.

Как указано в вашей таблице, значение TransactionLog.DocumentId должно существовать в трех таблицах (Invoice CreditNote DebitNote) вв то же время.Так что, если вставить только два из них, возможно, будет исключение.

enter image description here

Я думаю, вы действительно хотите, чтобы определение таблицы было таким.Я удаляю столбец TransactionLog.DocumentId и добавляю FK из PK трех таблиц в 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);
0 голосов
/ 19 сентября 2018

Полагаю, у вас там неправильные отношения.Как одна транзакция может иметь несколько счетов, но счет будет иметь только одну запись транзакции.Я могу ошибаться, потому что иногда мне кажется, что это один на один, но в любом случае я попробовал, и вот что вы хотите.

сущностей:

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; }
}  

и для вставки данных:

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();
    }  

и таблица будет выглядеть так:

enter image description here

0 голосов
/ 19 сентября 2018

Добавьте следующие конфигурации в 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...