4

約 6 つの銀行で 5000 のトランザクションを挿入していますが、データベースに重複した名前の銀行の行が 5000 あります。

public class Transaction
{
    [Key]
    public int Id { get; set; }
    public DateTime TransDate { get; set; }
    public decimal Value { get; set; }
    public string Description { get; set; }
    public Bank Bank { get; set; }
}

public class Bank
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class FinancialRecordContext : DbContext
{
    public FinancialRecordContext() : base("FinancialRecordDatabase") { }

    public DbSet<Transaction> Transactions { get; set; }

    public DbSet<Bank> Banks { get; set; }

    public Bank FindOrInsertBank(string bankName)
    {
        var bank = Banks.SingleOrDefault(b => b.Name == bankName);
        if (bank == null)
        {
            bank = new Bank { Name = bankName };
            Banks.Add(bank);
        }
        return bank;
    }
}

次に、挿入するために、いくつかのデータをループして、次のように挿入しています。

        using (var context = new FinancialRecordContext())
        {
            foreach (var t in data)
            {
                var tran = new Transaction
                {
                    Description = t.Description,
                    Value = t.Value,
                    TransDate = t.TransDate,
                    Bank = context.FindOrInsertBank(t.BankName)
                };
                context.Transactions.Add(tran);
            }
            context.SaveChanges();
        }

FindOrInsertBankメソッドは常にデータベースにアクセスしており、最近追加されたがコミットされた銀行をローカルで見ていないように見えます。これをどのように行うことができますか?

SaveChanges各銀行の挿入後に行う必要がありますか? 本当にやりたいことではありませんが、これをすべて 1 つのトランザクションにしたいと考えています。

4

2 に答える 2

2

変更トラッカーのクエリを試すことができます (これはデータベース クエリではなくメモリ内クエリです)。

using (var context = new FinancialRecordContext())
{
    foreach (var t in data)
    {
        Bank bank = context.ChangeTracker.Entries()
            .Where(e => e.Entity is Bank && e.State != EntityState.Deleted)
            .Select(e => e.Entity as Bank)
            .SingleOrDefault(b => b.Name == t.BankName);

        if (bank == null)
            bank = context.FindOrInsertBank(t.BankName);

        var tran = new Transaction
        {
            Description = t.Description,
            Value = t.Value,
            TransDate = t.TransDate,
            Bank = bank
        };
        context.Transactions.Add(tran);
    }
    context.SaveChanges();
}

編集

ここで変更トラッカーを使用すると、エンティティのキ​​ーではないため、パフォーマンスが低下する可能性がありBank.Name、クエリはエントリの線形検索になると思います。この場合、手書きの辞書を使用するのがより良い解決策かもしれません:

using (var context = new FinancialRecordContext())
{
    var dict = new Dictionary<string, Bank>();
    foreach (var t in data)
    {
        Bank bank;
        if (!dict.TryGetValue(t.BankName, out bank))
        {
            bank = context.FindOrInsertBank(t.BankName);
            dict.Add(t.BankName, bank);
        }

        var tran = new Transaction
        {
            Description = t.Description,
            Value = t.Value,
            TransDate = t.TransDate,
            Bank = bank
        };
        context.Transactions.Add(tran);
    }
    context.SaveChanges();
}
于 2013-04-13T13:52:57.257 に答える