C#EF使用ExecuteSqlCommand的正确方法
我一直在尝试一种方法,该方法接受一个列名称和一个我希望在基本测试数据库上更新的值,但我似乎无法使用SqlParameters获得结果?当我硬编码查询时,我看到db表被更新了吗 请务必理解我在以下查询中的错误:C#EF使用ExecuteSqlCommand的正确方法,c#,sql,entity-framework,C#,Sql,Entity Framework,我一直在尝试一种方法,该方法接受一个列名称和一个我希望在基本测试数据库上更新的值,但我似乎无法使用SqlParameters获得结果?当我硬编码查询时,我看到db表被更新了吗 请务必理解我在以下查询中的错误: public bool UpdateTestDataTable(string TID, string ColumnName, string ColumnValue) { try { if (!string.IsNullOrEmpty(TID))
public bool UpdateTestDataTable(string TID, string ColumnName, string ColumnValue)
{
try
{
if (!string.IsNullOrEmpty(TID))
{
using (var db = new TestDBContext())
{
var rId = db.TempDb.SingleOrDefault(p => p.TID == TID);
string s_q_el = @"UPDATE dbo.TempDb
SET @Column = @NewValue
WHERE TID = @TID
AND id = @DbId;";
//This Works
//string sql2 = @"UPDATE dbo.TempDb
// SET TestData1 = 'TestingABC'
// WHERE TID = '66A46552E9A0B912457CE804A54CE1AF'
// AND id = @DbId;";
var col = new SqlParameter("@Column", SqlDbType.NVarChar)
{
Value = ColumnName
};
var nval = new SqlParameter("@NewValue", SqlDbType.NVarChar)
{
Value = ColumnValue
};
var paid = new SqlParameter("@PAID", SqlDbType.NVarChar)
{
Value = TID
};
var id = new SqlParameter("@DbId", SqlDbType.Int)
{
Value = rId.Id
};
db.Database.ExecuteSqlCommand(s_q_el, parameters: new[] { col, nval, paid, id});
//db.Database.ExecuteSqlCommand(sql2);
db.SaveChanges();
return true;
}
}
else
{
return false;
}
}
catch(Exception UADT_EX)
{
Console.WriteLine($"Error: {UADT_EX.message}");
return false;
}
}
电话:
UpdateTestDataTable("66A46552E9A0B912457CE804A54CE1AF", "TestData1","BLAHBLAH123");
我已经测试了很多方法,但我觉得我完全忽略了这里显而易见的东西?
之所以采用这种方法,是因为我希望使用单个函数在整个测试应用程序中更新各种列数据
非常感谢
编辑
我根据收到的评论更新了查询,但以下做法是否不好
string s_q_el = $"UPDATE dbo.TempDb SET {ColumnName}= @NewValue WHERE TID = @TID AND id = @DbId;";
由于这会产生正确的结果,因为您有一个实体模型,为什么不使用反射呢。与DbContext上的帮助器方法类似:
public void UpdateEntity<T>(int id, string propertyName, string propertyValue) where T:class
{
var entity = this.Set<T>().Find(id);
var prop = typeof(T).GetProperty(propertyName);
var val = Convert.ChangeType(propertyValue, prop.PropertyType);
prop.SetValue(entity, val);
this.SaveChanges();
}
public void UpdateEntity(int-id,string-propertyName,string-propertyValue),其中T:class
{
var entity=this.Set().Find(id);
var prop=typeof(T).GetProperty(propertyName);
var val=Convert.ChangeType(propertyValue,prop.PropertyType);
属性设置值(实体,val);
这是SaveChanges();
}
如果您知道密钥属性名称,甚至可以在不首先从数据库获取实体的情况下执行此操作。乙二醇
public void UpdateEntity<T>(int id, string keyPropertyName, string propertyName, string propertyValue) where T:class, new()
{
var entity = new T();
typeof(T).GetProperty(keyPropertyName).SetValue(entity,Id);
this.Set<T>().Add(entity);
var prop = typeof(T).GetProperty(propertyName);
var val = Convert.ChangeType(propertyValue, prop.PropertyType);
prop.SetValue(entity, val);
this.Entry(entity).State = EntityState.Unchanged;
foreach (var p in this.Entry(entity).Properties)
{
p.IsModified = p.Metadata.Name == propertyName;
}
this.SaveChanges();
}
public void UpdateEntity(int-id,string-keyPropertyName,string-propertyName,string-propertyValue),其中T:class,new()
{
var entity=newt();
typeof(T).GetProperty(keyPropertyName).SetValue(实体,Id);
this.Set().Add(实体);
var prop=typeof(T).GetProperty(propertyName);
var val=Convert.ChangeType(propertyValue,prop.PropertyType);
属性设置值(实体,val);
this.Entry(entity).State=EntityState.Unchanged;
foreach(此.Entry(entity.Properties)中的var p)
{
p、 IsModified=p.Metadata.Name==propertyName;
}
这是SaveChanges();
}
既然您有一个实体模型,为什么不直接使用反射呢。与DbContext上的帮助器方法类似:
public void UpdateEntity<T>(int id, string propertyName, string propertyValue) where T:class
{
var entity = this.Set<T>().Find(id);
var prop = typeof(T).GetProperty(propertyName);
var val = Convert.ChangeType(propertyValue, prop.PropertyType);
prop.SetValue(entity, val);
this.SaveChanges();
}
public void UpdateEntity(int-id,string-propertyName,string-propertyValue),其中T:class
{
var entity=this.Set().Find(id);
var prop=typeof(T).GetProperty(propertyName);
var val=Convert.ChangeType(propertyValue,prop.PropertyType);
属性设置值(实体,val);
这是SaveChanges();
}
如果您知道密钥属性名称,甚至可以在不首先从数据库获取实体的情况下执行此操作。乙二醇
public void UpdateEntity<T>(int id, string keyPropertyName, string propertyName, string propertyValue) where T:class, new()
{
var entity = new T();
typeof(T).GetProperty(keyPropertyName).SetValue(entity,Id);
this.Set<T>().Add(entity);
var prop = typeof(T).GetProperty(propertyName);
var val = Convert.ChangeType(propertyValue, prop.PropertyType);
prop.SetValue(entity, val);
this.Entry(entity).State = EntityState.Unchanged;
foreach (var p in this.Entry(entity).Properties)
{
p.IsModified = p.Metadata.Name == propertyName;
}
this.SaveChanges();
}
public void UpdateEntity(int-id,string-keyPropertyName,string-propertyName,string-propertyValue),其中T:class,new()
{
var entity=newt();
typeof(T).GetProperty(keyPropertyName).SetValue(实体,Id);
this.Set().Add(实体);
var prop=typeof(T).GetProperty(propertyName);
var val=Convert.ChangeType(propertyValue,prop.PropertyType);
属性设置值(实体,val);
this.Entry(entity).State=EntityState.Unchanged;
foreach(此.Entry(entity.Properties)中的var p)
{
p、 IsModified=p.Metadata.Name==propertyName;
}
这是SaveChanges();
}
如注释中所述,您不能参数化列名,但可以构建一个存储过程,该存储过程可以使用参数并从中生成SQL:
CREATE PROCEDURE updateFromParameters
@column varchar(max),
@newValue varchar(max),
@TID varchar(max),
@id int
AS
DECLARE @s_q_el varchar(max)
SET @s_q_el = 'UPDATE dbo.TempDB '
+ 'SET ' + @column + ' = ''' + @newValue + ''''
+ 'WHERE TID = ''' + @TID + ''''
+ 'id = ' + @id
EXEC @s_q_el
然后只需从C代码执行存储过程:
如注释中所述,您不能参数化列名,但可以构建一个存储过程,该存储过程可以使用参数并从中生成SQL:
CREATE PROCEDURE updateFromParameters
@column varchar(max),
@newValue varchar(max),
@TID varchar(max),
@id int
AS
DECLARE @s_q_el varchar(max)
SET @s_q_el = 'UPDATE dbo.TempDB '
+ 'SET ' + @column + ' = ''' + @newValue + ''''
+ 'WHERE TID = ''' + @TID + ''''
+ 'id = ' + @id
EXEC @s_q_el
然后只需从C代码执行存储过程:
如图所示,您可以进行轻微修改:
string s_q_el = $@"UPDATE dbo.TempDb
SET {ColumnName} = @NewValue
WHERE TID = @TID
AND id = @DbId;";
var nval = new SqlParameter("@NewValue", SqlDbType.NVarChar)
{
Value = ColumnValue
};
var paid = new SqlParameter("@PAID", SqlDbType.NVarChar)
{
Value = TID
};
var id = new SqlParameter("@DbId", SqlDbType.Int)
{
Value = rId.Id
};
db.Database.ExecuteSqlCommand(s_q_el, nval, paid, id);
或者您也可以这样做:
string s_q_el = $@"UPDATE dbo.TempDb
SET {ColumnName} = {{0}}
WHERE TID = {{1}}
AND id = {{2}};";
db.Database.ExecuteSqlCommand(s_q_el, nval, paid, id);
在后一个示例中,SQL仍然使用参数发送到后端,Linq会自动将它们创建为名为@p0、@p1。。。并具有相应的约束力。这可能会有一些问题,比如没有选择正确的数据类型,但在大多数情况下都会起作用
使用ExecuteSqlCommand有时非常方便,并且比获取实体、更新和保存更可取(即:批量更新或删除-如果您的条件可能返回多行进行更新)。您可以如所示执行此操作,稍加修改:
string s_q_el = $@"UPDATE dbo.TempDb
SET {ColumnName} = @NewValue
WHERE TID = @TID
AND id = @DbId;";
var nval = new SqlParameter("@NewValue", SqlDbType.NVarChar)
{
Value = ColumnValue
};
var paid = new SqlParameter("@PAID", SqlDbType.NVarChar)
{
Value = TID
};
var id = new SqlParameter("@DbId", SqlDbType.Int)
{
Value = rId.Id
};
db.Database.ExecuteSqlCommand(s_q_el, nval, paid, id);
或者您也可以这样做:
string s_q_el = $@"UPDATE dbo.TempDb
SET {ColumnName} = {{0}}
WHERE TID = {{1}}
AND id = {{2}};";
db.Database.ExecuteSqlCommand(s_q_el, nval, paid, id);
在后一个示例中,SQL仍然使用参数发送到后端,Linq会自动将它们创建为名为@p0、@p1。。。并具有相应的约束力。这可能会有一些问题,比如没有选择正确的数据类型,但在大多数情况下都会起作用
使用ExecuteSqlCommand有时非常方便,并且比获取实体、更新和保存(即:批量更新或删除-如果您的条件可能会返回多行进行更新)更可取。您不能参数化列名(或表名)。参数仅用于传递值。值是一种基本数据类型,如字符串、数字、guid、日期时间等。啊,他妈的,照你猜的做,我没想到会尝试另一种方法,然后你不能参数化列名(或表名)。参数仅用于传递值。值是一种原始数据类型,如字符串、数字、guid、日期时间等。啊,该死的,就像你猜的那样,我没想到会尝试另一种方法,然后啊,实际上看起来更好更干净,我现在要测试一下,因为我在过去一周才开始学习EF。非常感谢这一点,我也在msdn上找到了关于Set的参考资料,因为我想完全理解这一点,可以说它工作得非常好,正在做我需要的事情。我真的很欣赏它。事实上,它看起来更好、更干净,我现在将测试这一点,因为我在过去一周才开始学习EF。非常感谢这一点,我也在msdn上找到了关于Set的参考资料,因为我想完全理解这一点,可以说这非常有效,并且正在做我需要的事情。非常感谢