imo*_*din 17 c# sql-server stored-procedures dapper
我有一个存储过程InsertCars
,它接受用户定义的表类型列表CarType
.
CREATE TYPE dbo.CarType
AS TABLE
(
CARID int null,
CARNAME varchar(800) not null,
);
CREATE PROCEDURE dbo.InsertCars
@Cars AS CarType READONLY
AS
-- RETURN COUNT OF INSERTED ROWS
END
Run Code Online (Sandbox Code Playgroud)
我需要从Dapper调用这个存储过程.我用Google搜索并找到了一些解决方案.
var param = new DynamicParameters(new{CARID= 66, CARNAME= "Volvo"});
var result = con.Query("InsertCars", param, commandType: CommandType.StoredProcedure);
Run Code Online (Sandbox Code Playgroud)
但是我收到一个错误:
过程或函数InsertCars指定了太多参数
存储过程也InsertCars
返回插入行的计数; 我需要得到这个值.
问题的根源在哪里?
我的问题是我在通用列表中有汽车List<Car> Cars
,我希望将此列表传递给存储过程.它优雅的方式存在怎么办?
public class Car
{
public CarId { get; set; }
public CarName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助
EDITED
我找到了解决方案
要么
所以我尝试制作自己的愚蠢助手类
class CarDynamicParam : Dapper.SqlMapper.IDynamicParameters
{
private Car car;
public CarDynamicParam(Car car)
{
this.car = car;
}
public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
var sqlCommand = (SqlCommand)command;
sqlCommand.CommandType = CommandType.StoredProcedure;
var carList = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
Microsoft.SqlServer.Server.SqlMetaData[] tvpDefinition =
{
new Microsoft.SqlServer.Server.SqlMetaData("CARID", SqlDbType.Int),
new Microsoft.SqlServer.Server.SqlMetaData("CARNAME", SqlDbType.NVarChar, 100),
};
var rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvpDefinition);
rec.SetInt32(0, car.CarId);
rec.SetString(1, car.CarName);
carList.Add(rec);
var p = sqlCommand.Parameters.Add("Cars", SqlDbType.Structured);
p.Direction = ParameterDirection.Input;
p.TypeName = "CarType";
p.Value = carList;
}
}
Run Code Online (Sandbox Code Playgroud)
使用
var result = con.Query("InsertCars", new CarDynamicParam(car), commandType: CommandType.StoredProcedure);
Run Code Online (Sandbox Code Playgroud)
我得到例外
使用多映射API时,如果您具有Id以外的密钥,请确保设置splitOn参数.
堆栈跟踪:
at Dapper.SqlMapper.GetDynamicDeserializer(IDataRecord reader, Int32 startBound, Int32 length, Boolean returnNullIfFirstMissing) in c:\Dev\Dapper\Dapper\SqlMapper.cs:line 1308
at Dapper.SqlMapper.GetDeserializer(Type type, IDataReader reader, Int32 startBound, Int32 length, Boolean returnNullIfFirstMissing) in c:\Dev\Dapper\Dapper\SqlMapper.cs:line 1141
at Dapper.SqlMapper.<QueryInternal>d__d`1.MoveNext() in c:\Dev\Dapper\Dapper\SqlMapper.cs:line 819
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in c:\Dev\Dapper\Dapper\SqlMapper.cs:line 770
at Dapper.SqlMapper.Query(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in c:\Dev\Dapper\Dapper\SqlMapper.cs:line 715
Run Code Online (Sandbox Code Playgroud)
怎么了?
固定:
打电话con.Execute
来con.Query
Ehs*_*san 16
我的问题是我在通用列表List Cars中有汽车,我希望将此列表传递给存储过程.它优雅的方式存在怎么办?
您需要将通用列表Car转换为数据表,然后将其传递给storedprocedure.需要注意的是,字段的顺序必须与数据库中用户定义的表类型中定义的顺序相同.否则数据将无法正常保存.并且它必须具有相同数量的列.
我使用此方法将List转换为DataTable.您可以像yourList.ToDataTable()一样调用它
public static DataTable ToDataTable<T>(this List<T> iList)
{
DataTable dataTable = new DataTable();
PropertyDescriptorCollection propertyDescriptorCollection =
TypeDescriptor.GetProperties(typeof(T));
for (int i = 0; i < propertyDescriptorCollection.Count; i++)
{
PropertyDescriptor propertyDescriptor = propertyDescriptorCollection[i];
Type type = propertyDescriptor.PropertyType;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
type = Nullable.GetUnderlyingType(type);
dataTable.Columns.Add(propertyDescriptor.Name, type);
}
object[] values = new object[propertyDescriptorCollection.Count];
foreach (T iListItem in iList)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = propertyDescriptorCollection[i].GetValue(iListItem);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
Run Code Online (Sandbox Code Playgroud)
我知道这有点老了,但是我想无论如何都会发布,因为我一直在努力使它变得更简单。我希望我使用我创建的NuGet包做到了这一点,该包将允许以下代码:
public class CarType
{
public int CARID { get; set; }
public string CARNAME{ get; set; }
}
var cars = new List<CarType>{new CarType { CARID = 1, CARNAME = "Volvo"}};
var parameters = new DynamicParameters();
parameters.AddTable("@Cars", "CarType", cars)
var result = con.Query("InsertCars", parameters, commandType: CommandType.StoredProcedure);
Run Code Online (Sandbox Code Playgroud)
NuGet软件包:https : //www.nuget.org/packages/Dapper.ParameterExtensions/0.2.0 仍处于早期阶段,因此可能无法与所有内容一起使用!
请阅读自述文件,并随时在GitHub上进行贡献:https : //github.com/RasicN/Dapper-Parameters
归档时间: |
|
查看次数: |
23358 次 |
最近记录: |