我正在寻找一种只在Dapper中更新设置属性的方法。即只有在非空属性时才更新实体的属性。
我用如下所示的相当粗略的方法解决了同样的问题,但我相信应该采用更简洁的方式来做到这一点。
public void UpdateCustomer(Customer cust)
{
try
{
StringBuilder sb = new StringBuilder("UPDATE CUSTOMER_SETUP SET DATE_MODIFIED = @DATE_MODIFIED ");
if(cust.BUSINESSNAME != null) sb.Append(",BUSINESSNAME = @BUSINESSNAME ");
if (cust.BUSINESS_ADDRESS != null) sb.Append(",BUSINESS_ADDRESS = @BUSINESS_ADDRESS ");
if (cust.CONTACT_NAME != null) sb.Append(",CONTACT_NAME = @CONTACT_NAME ");
if (cust.CONTACT_TITLE != null) sb.Append(",CONTACT_TITLE = @CONTACT_TITLE ");
if (cust.CONTACT_PHONE1 != null) sb.Append(",CONTACT_PHONE1 = @CONTACT_PHONE1 ");
if (cust.CONTACT_PHONE2 != null) sb.Append(",CONTACT_PHONE2 = @CONTACT_PHONE2 ");
if (cust.CONTACT_EMAIL != null) sb.Append(",CONTACT_EMAIL = @CONTACT_EMAIL ");
if (cust.CONTACT_URL != null) sb.Append(",CONTACT_URL = @CONTACT_URL ");
if (cust.DATE_CREATED != null) sb.Append(",DATE_CREATED = @DATE_CREATED ");
if (cust.CUSTOMER_TYPE != null) sb.Append(",CUSTOMER_TYPE = @CUSTOMER_TYPE ");
if (cust.SUBSCRIPTION_TYPE != null) sb.Append(",SUBSCRIPTION_TYPE = @SUBSCRIPTION_TYPE ");
sb.Append("WHERE ID = @ID ");
sb.Append("; SELECT CAST(SCOPE_IDENTITY() as int ");
var sql = sb.ToString();
using (connection = new SqlConnection(connectString))
{
connection.Execute(sql, cust);
}
}
catch (Exception ex)
{
throw ex;
}
}
答案 0 :(得分:2)
您正在寻找的功能称为更改跟踪。此功能是更大的工作单元模式的一部分。
Dapper不支持更改跟踪。
Dapper的附加组件很少有人在不同的级别上支持这一点。有关比较图表,请参阅this博文。如图表所示,Dapper.Contrib和Dapper.Rainbow以不同的方式支持它。
编辑:回答您的评论
正如@MarcGravell在评论中所说,POCO属性的null
值很常见。它并不总是意味着“不要更新那个领域”。这也可能意味着“将该数据库字段设置为null
(或DBNull
)”。由于属性值null
没有任何保证意义,因此大多数ORM以与Dapper相同的方式实现它。
答案 1 :(得分:0)
我们将Dapper.Rainbow的Snapshotter
包装成改变跟踪器。您需要一个db对象的实例才能工作。
它非常适合我们提供您可以很容易地用来生成您所追求的SQL的字典。
它可能看起来像这样:
public class Foo{public string Name{get;set;}}
var foo = new Foo();
var snapshotter = Snapshotter.Start(foo);
foo.Name = "A new name";
var dynparams = snapshotter.Diff(); //we basically wrap the snapshotter to give a dict here, but it's basically the same thing
foreach(var name in dynparams.ParameterNames){
sb.Append($",{name} = @{dynparams[name]} ");
}
答案 2 :(得分:0)
自己动手。
为模型添加私有集合,读取时复制数据。更新时比较新旧。根据需要构建 SQL 语句。
通过增加数据库前处理,而不是让列“干火”给数据库供应商,是否会带来净性能提升?我认为大多数数据库供应商都知道列数据何时不变,并且会在必要时排除这些列,例如特定列上的更新触发器。
答案 3 :(得分:0)
这是使用您想要的 Dapper 的更新查询示例。或许能帮到你。
public async Task<bool> UpdateDataByIdAsync(Data data)
{
using MySqlConnection connection = new MySqlConnection("your connection string");
const string sqlQuery = @"Update Datas Set name = @name, description = @description, tags = @tags
where data_id = @data_id;";
var rowAffected = await connection.ExecuteAsync(sqlQuery, data);
return rowAffected > 0;
}