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(); }解决方案都有竞争条件。如果你走那条路,当你打电话时SubmitChanges,你必须考虑到a)a)SqlException可以为重复插入引发,或者b)你可能在表中有重复的记录。

幸运的是,我们可以使用数据库通过强制唯一性来避免竞争条件。下面的代码假定表上有一个主键或唯一约束,以防止插入重复记录。

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

同意马克思的回答,但见注1。

注意 1:恕我直言,调用辅助方法是不明智db.SubmitChanges()的,因为您可能会破坏上下文事务。这意味着,如果您InsertIfNotExists<TEntity>在多个实体的复杂更新中间调用 ,您不是一次保存更改,而是分步保存更改。

注 2:该InsertIfNotExists<TEntity>方法是一种非常通用的方法,适用于任何场景。如果您只想区分从数据库加载的实体和从代码创建的实体,可以使用OnLoadedEntity 类的部分方法,如下所示:

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 回答