Как вставить коллекцию IEnumerable <T> с dapper-dot-net
Да, здесь есть вопросы и здесь о том, как вставлять записи с dapper-dot-net, Однако ответы, в то время как информативные, похоже, не указывали мне в правильном направлении. Вот ситуация: перемещение данных с SqlServer на MySql. Чтение записей в IEnumerable<WTUser>
выполняется легко, но я просто ничего не получаю от вставки. Во-первых, "код движущихся записей":
// moving data
Dim session As New Session(DataProvider.MSSql, "server", _
"database")
Dim resources As List(Of WTUser) = session.QueryReader(Of WTUser)("select * from tbl_resource")
session = New Session(DataProvider.MySql, "server", "database", _
"user", "[email protected]$$w0rd")
// *edit* - corrected parameter notation with '@'
Dim strInsert = "INSERT INTO tbl_resource (ResourceName, ResourceRate, ResourceTypeID, ActiveYN) " & _
"VALUES (@ResourceName, @ResourceRate, @ResourceType, @ActiveYN)"
Dim recordCount = session.WriteData(Of WTUser)(strInsert, resources)
// session Methods
Public Function QueryReader(Of TEntity As {Class, New})(ByVal Command As String) _
As IEnumerable(Of TEntity)
Dim list As IEnumerable(Of TEntity)
Dim cnn As IDbConnection = dataAgent.NewConnection
list = cnn.Query(Of TEntity)(Command, Nothing, Nothing, True, 0, CommandType.Text).ToList()
Return list
End Function
Public Function WriteData(Of TEntity As {Class, New})(ByVal Command As String, ByVal Entities As IEnumerable(Of TEntity)) _
As Integer
Dim cnn As IDbConnection = dataAgent.NewConnection
// *edit* if I do this I get the correct properties, but no data inserted
//Return cnn.Execute(Command, New TEntity(), Nothing, 15, CommandType.Text)
// original Return statement
Return cnn.Execute(Command, Entities, Nothing, 15, CommandType.Text)
End Function
cnn.Query и cnn.Execute вызовите методы расширения dapper. Теперь класс WTUser (обратите внимание: имя столбца изменилось с "WindowsName" на SqlServer на "ResourceName" в MySql, таким образом, два свойства указывали на одно и то же поле):
Public Class WTUser
// edited for brevity - assume the following all have public get/set methods
Public ActiveYN As String
Public ResourceID As Integer
Public ResourceRate As Integer
Public ResourceType As Integer
Public WindowsName As String
Public ResourceName As String
End Class
Я получаю исключение из dapper: "WTUser не поддерживается Dapper". Этот метод в DataMapper (dapper):
private static Action<IDbCommand, object> CreateParamInfoGenerator(Type OwnerType)
{
string dmName = string.Format("ParamInfo{0}", Guid.NewGuid());
Type[] objTypes = new[] { typeof(IDbCommand), typeof(object) };
var dm = new DynamicMethod(dmName, null, objTypes, OwnerType, true); // << - here
// emit stuff
// dm is instanced, now ...
foreach (var prop in OwnerType.GetProperties().OrderBy(p => p.Name))
В этот момент OwnerType =
System.Collections.Generic.List`1 [[CRMBackEnd.WTUser, CRMBE, версия = 1.0.0.0, Culture = нейтрально, PublicKeyToken = null]], mscorlib, Версия = 2.0.0.0, Культура = нейтральная, PublicKeyToken = b77a5c561934e089
Кажется, что OwnerType должен быть CRMBackEnd.WTUser
... not List<CRMBackEnd.WTUser>
...??? потому что происходит то, что свойства коллекции повторяются: Count, Capacity и т.д. Что мне не хватает?
Обновить
Если я изменил session.WriteData как:
Public Function WriteData(Of TEntity As {Class, New})(ByVal Command As String, _
ByVal Entities As IEnumerable(Of TEntity)) _
As Integer
Dim cnn As IDbConnection = dataAgent.NewConnection
Dim records As Integer
For Each entity As TEntity In Entities
records += cnn.Execute(Command, entity, Nothing, 15, CommandType.Text)
Next
Return records
End Function
записи вставляются красиво... но я не думал, что это было бы необходимо, если бы приведенные примеры, например:
connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
).IsEqualTo(3); // 3 rows inserted: "1,1", "2,2" and "3,3"
... из dapper-dot-net
Ответы
Ответ 1
Я просто добавил тест для этого:
class Student
{
public string Name {get; set;}
public int Age { get; set; }
}
public void TestExecuteMultipleCommandStrongType()
{
connection.Execute("create table #t(Name nvarchar(max), Age int)");
int tally = connection.Execute(@"insert #t (Name,Age) values(@Name, @Age)", new List<Student>
{
new Student{Age = 1, Name = "sam"},
new Student{Age = 2, Name = "bob"}
});
int sum = connection.Query<int>("select sum(Age) from #t drop table #t").First();
tally.IsEqualTo(2);
sum.IsEqualTo(3);
}
Он работает как рекламируемый. Я сделал несколько поправок к тому, как работает multi-exec (так что он немного быстрее и поддерживает объект []).
Я предполагаю, что у вас были проблемы, потому что у вас не было свойства getter во всех ваших полях на WTUser
. Все параметры должны иметь свойства считывателя, мы не поддерживаем вытягивание этого из полей, для этого требуется комплексный синтаксический анализ.
Дополнительной точкой, вызвавшей проблему, является передача dapper параметра с неподдерживаемым отображением.
Например, следующий класс не поддерживается как параметр:
class Test
{
public int Id { get; set; }
public User User {get; set;}
}
cnn.Query("select * from Tests where Id = @Id", new Test{Id = 1}); // used to go boom
Проблема в том, что dapper сделал не синтаксический анализ SQL, он предположил, что все реквизиты настраиваются как параметры, но не смогли разрешить тип SQL для User
.
Последний rev разрешает это