12

レコードがまだテーブルに存在しない場合に、レコードを挿入する簡単な方法があるかどうか知りたいです。私はまだ LINQ to SQL のスキルを構築しようとしています。

これが私が持っているものですが、もっと簡単な方法があるはずです。

public static TEntity InsertIfNotExists<TEntity>
(
    DataContext db,
    Table<TEntity> table,
    Func<TEntity,bool> where,
    TEntity record
)
    where TEntity : class
{
    TEntity existing = table.SingleOrDefault<TEntity>(where);

    if (existing != null)
    {
        return existing; 
    }
    else
    {
        table.InsertOnSubmit(record);

        // Can't use table.Context.SubmitChanges()
        // 'cause it's read-only

        db.SubmitChanges();
    }

    return record;
}
4

4 に答える 4

14
public static void InsertIfNotExists<TEntity>
                    (this Table<TEntity> table,
                     TEntity entity,
                     Expression<Func<TEntity,bool>> predicate)
    where TEntity : class
{ 
    if (!table.Any(predicate)) 
    {
        table.InsertOnSubmit(record);
        table.Context.SubmitChanges();
    }
 }


table.InsertIfNotExists(entity, e=>e.BooleanProperty);
于 2008-09-19T08:30:35.650 に答える
12

他の人が指摘したように、if (!Any()) { InsertOnSubmit(); }ソリューションにはすべて競合状態があります。そのルートに行く場合、 を呼び出すときに、a) 重複挿入に対して a が発生SubmitChangesする可能性があるか、b) テーブルに重複レコードがある可能性があることを考慮する必要があります。SqlException

幸いなことに、データベースを使用して一意性を強制することで競合状態を回避できます。次のコードは、重複レコードの挿入を防ぐために、テーブルに主キーまたは一意の制約があることを前提としています。

using (var db = new DataContext()) {

    // Add the new (possibly duplicate) record to the data context here.

    try {
        db.SubmitChanges();
    } catch (SqlException ex) {
        const int violationOfPrimaryKeyContraint = 2627;
        const int violationOfUniqueConstraint = 2601;
        var duplicateRecordExceptionNumbers = new [] {
            violationOfPrimaryKeyContraint, violationOfUniqueConstraint
        };
        if (!duplicateRecordExceptionNumbers.Contains(ex.Number)) {
            throw;
        }
    }
}

さて... 他のデータベース更新を伴うバッチ トランザクションで挿入を実行する必要がある場合、事態はかなり複雑になります。

于 2011-01-25T22:02:09.073 に答える
5

marxidad's answerに同意しますが、注 1 を参照してください。

db.SubmitChanges()注1:コンテキストトランザクションを壊す可能性があるため、ヘルパーメソッドを呼び出すのは賢明ではありません。これはInsertIfNotExists<TEntity>、複数のエンティティの複雑な更新の途中で を呼び出すと、変更を一度に保存するのではなく、段階的に保存することを意味します。

注 2: このInsertIfNotExists<TEntity>方法は、あらゆるシナリオで機能する非常に一般的な方法です。データベースから読み込まれたエンティティと、コードから作成されたエンティティを区別するだけの場合は、次のOnLoadedように Entity クラスの部分メソッドを利用できます。

public partial class MyEntity
{
    public bool IsLoaded { get; private set; }
    partial void OnLoaded()
    {
        IsLoaded = true;
    }
}

その場合 (および注 1)、InsertIfNotExists 機能は次のように縮小されます。

if (!record.IsLoaded)
    db.InsertOnSubmit(record);
于 2008-09-19T09:06:44.143 に答える
4

マークの答えの小さな修正:

エンティティが主キーで存在するかどうかのみを確認する場合は、Marke の回答を次のように使用できます。

public static void InsertIfNotExists<TEntity>
                    (this Table<TEntity> table
                     , TEntity entity
                    ) where TEntity : class
    {
        if (!table.Contains(entity))
        {
            table.InsertOnSubmit(entity);

        }
    }
于 2010-01-21T10:37:12.220 に答える