Ich habe eine gespeicherte Prozedur InsertCars
die eine Liste des benutzerdefinierten Tabellentyps 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
Ich muss diese gespeicherte Prozedur von Dapper aufrufen. Ich habe es gegoogelt und ein paar Lösungen gefunden.
var param = new DynamicParameters(new{CARID= 66, CARNAME= "Volvo"});
var result = con.Query("InsertCars", param, commandType: CommandType.StoredProcedure);
Aber ich bekomme einen Fehler:
Prozedur oder Funktion InsertCars hat zu viele Argumente angegeben
Auch gespeicherte Prozedur InsertCars
gibt die Anzahl der eingefügten Zeilen zurück; Ich brauche diesen Wert.
Wo liegt die Wurzel des Problems?
Mein Problem ist auch, dass ich Autos in der generischen Liste List<Car> Cars
und ich möchte diese Liste übergeben, um Verfahren zu speichern. Es existiert eine elegante Art, wie es geht?
public class Car
{
public CarId { get; set; }
public CarName { get; set; }
}
Danke für die Hilfe
BEARBEITET
Ich habe Lösungen gefunden
Unterstützt Dapper SQL 2008 Table-Valued Parameters?
oder
Unterstützt Dapper SQL 2008 Table-Valued Parameters 2?
Also versuche ich selber eine dumme Helferklasse zu machen
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;
}
}
Benutzen
var result = con.Query("InsertCars", new CarDynamicParam(car), commandType: CommandType.StoredProcedure);
Ich bekomme eine Ausnahme
Wenn Sie die Multi-Mapping-APIs verwenden, stellen Sie sicher, dass Sie den splitOn-Parameter festlegen, wenn Sie andere Schlüssel als Id haben.
StackTrace:
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
Was ist falsch?
FEST:
Rufen Sie con.Execute
statt con.Query
Mein Problem ist auch, dass ich Autos in der generischen Liste List Cars habe und diese Liste an die gespeicherte Prozedur übergeben möchte. Es gibt eine elegante Art und Weise, wie es geht?
Sie müssen Ihr generisches Listenauto in eine Datentabelle konvertieren und es dann an das gespeicherte Verfahren übergeben. Beachten Sie, dass die Reihenfolge Ihrer Felder mit der im benutzerdefinierten Tabellentyp in der Datenbank definierten übereinstimmen muss. Andernfalls werden die Daten nicht ordnungsgemäß gespeichert. Und es muss auch die gleiche Anzahl von Spalten haben .
Ich benutze diese Methode, um List in DataTable zu konvertieren. Sie können es wie yourList.ToDataTable () aufrufen.
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;
}
Ich weiß, dass dies ein bisschen alt ist, aber ich dachte, ich würde es trotzdem posten, da ich versucht habe, es ein bisschen einfacher zu machen. Ich hoffe, ich habe dies mit einem von mir erstellten NuGet-Paket getan, das Code wie den folgenden zulässt:
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);
NuGet-Paket: https://www.nuget.org/packages/Dapper.ParameterExtensions/0.2.0 Da es sich noch in einem frühen Stadium befindet, funktioniert es möglicherweise nicht mit allen!
Bitte lesen Sie die README-Datei und schreiben Sie einen Beitrag zu GitHub: https://github.com/RasicN/Dapper-Parameters