如何为LINQ到SQL编写Upsert?
因此,我想为LINQ to SQL编写一个通用的Upsert函数,但在概念化如何执行时遇到了一些问题。我希望它能像这样工作:如何为LINQ到SQL编写Upsert?,linq,linq-to-sql,Linq,Linq To Sql,因此,我想为LINQ to SQL编写一个通用的Upsert函数,但在概念化如何执行时遇到了一些问题。我希望它能像这样工作: var db = new DataContext(); db.Customers.UpsertOnSubmit(customer); 所以它必须在某种程度上是通用的,我猜是表上的扩展方法。在确定基础表的主键时,我已经做到了这一点: var context = source.Context; var table = context.Mapping.GetTable(sou
var db = new DataContext();
db.Customers.UpsertOnSubmit(customer);
所以它必须在某种程度上是通用的,我猜是表上的扩展方法。在确定基础表的主键时,我已经做到了这一点:
var context = source.Context;
var table = context.Mapping.GetTable(source.GetType());
var primaryMember = table.RowType.DataMembers.SingleOrDefault(m => m.IsPrimaryKey);
我假设有必要用它来组成一个查询,以判断该项是否已经在数据库中,但此时我真的不知道该如何处理它。我做了类似的事情,但方法不同。每个实体都实现了
ienty
。如果对象是新的或现有的,IEntity
的属性之一是状态。然后,我为每个实体实现该功能,如:
public EntityState EntityState
{
get
{
if (_Id > 0)
return EntityState.Exisiting;
else
return EntityState.New;
}
}
然后,泛型Upsert
可以是(在泛型存储库类型类上):
public虚拟空向上插入(Ta实体)
助教:在哪里上课
{
如果(!(实体为实体))
抛出新异常(“T必须是IEntity类型”);
if(((entity)entity).EntityState==EntityState.Exisiting)
GetTable().Attach(实体,true);
其他的
GetTable().InsertOnSubmit(实体);
}
private System.Data.Linq.Table GetTable()
助教:在哪里上课
{
返回_dataContext.Context.GetTable();
}
如果您从另一个datacontext进行附加,请确保您的对象上有时间戳。简短回答: 抓住这个: 解释 要在LINQtoSQL中执行UPSERT而不首先查询记录,可以执行以下操作。它仍然会点击数据库一次,以检查记录是否存在,但不会拉取记录:
var blob = new Blob { Id = "some id", Value = "some value" }; // Id is primary key (PK)
if (dbContext.Blobs.Contains(blob)) // if blob exists by PK then update
{
// This will update all columns that are not set in 'original' object. For
// this to work, Blob has to have UpdateCheck=Never for all properties except
// for primary keys. This will update the record without querying it first.
dbContext.Blobs.Attach(blob, original: new Blob { Id = blob.Id });
}
else // insert
{
dbContext.Blobs.InsertOnSubmit(blob);
}
dbContext.Blobs.SubmitChanges();
扩展方法
我为它想出了以下扩展方法
public static class EntityExtensionMethods
{
public static void InsertOrUpdateOnSubmit<TEntity>(this Table<TEntity> table, TEntity entity, TEntity original = null)
where TEntity : class, new()
{
if (table.Contains(entity)) // if entity exists by PK then update
{
if (original == null)
{
// Create original object with only primary keys set
original = new TEntity();
var entityType = typeof(TEntity);
var dataMembers = table.Context.Mapping.GetMetaType(entityType).DataMembers;
foreach (var member in dataMembers.Where(m => m.IsPrimaryKey))
{
var propValue = entityType.GetProperty(member.Name).GetValue(entity, null);
entityType.InvokeMember(member.Name, BindingFlags.SetProperty, Type.DefaultBinder,
original, new[] {propValue});
}
}
// This will update all columns that are not set in 'original' object. For
// this to work, entity has to have UpdateCheck=Never for all properties except
// for primary keys. This will update the record without querying it first.
table.Attach(entity, original);
}
else // insert
{
table.InsertOnSubmit(entity);
}
}
}
我在这个要点中添加了更多的扩展方法:好吧。。。upsert的全部要点是,您不知道它是否存在,您只希望数据库具有新内容;upsert将为您保存“额外往返”以确定该值。你的解决方案不能回答这个问题;需要的是一个sql
合并,如下所述:。这个答案适用于实体框架。有关LINQ到SQL解决方案,请参见我的答案。
public static class EntityExtensionMethods
{
public static void InsertOrUpdateOnSubmit<TEntity>(this Table<TEntity> table, TEntity entity, TEntity original = null)
where TEntity : class, new()
{
if (table.Contains(entity)) // if entity exists by PK then update
{
if (original == null)
{
// Create original object with only primary keys set
original = new TEntity();
var entityType = typeof(TEntity);
var dataMembers = table.Context.Mapping.GetMetaType(entityType).DataMembers;
foreach (var member in dataMembers.Where(m => m.IsPrimaryKey))
{
var propValue = entityType.GetProperty(member.Name).GetValue(entity, null);
entityType.InvokeMember(member.Name, BindingFlags.SetProperty, Type.DefaultBinder,
original, new[] {propValue});
}
}
// This will update all columns that are not set in 'original' object. For
// this to work, entity has to have UpdateCheck=Never for all properties except
// for primary keys. This will update the record without querying it first.
table.Attach(entity, original);
}
else // insert
{
table.InsertOnSubmit(entity);
}
}
}
var blob = new Blob { Id = "some id", Value = "some value" }; // Id is primary key (PK)
dbContext.Blobs.InsertOrUpdateOnSubmit(blob);
dbContext.Blobs.SubmitChanges();