1.Dapper does not support mapping of anonymous types well and has serious bugs
2.The advantage of anonymity, I don't have to say much about it.
3.What about his relationship with Dapper?
Example1
I have a type Student (id, age, sex, sid) and a school (sid, sname)。
I get the (id, age, sname) of these two types by connecting queries, but I don't want to define a new type.
``` c#
public List
{
return connection.Query
}
I have defined the following methods, which can be solved
``` c#
var list = Query((stu,sch)=>new
{
stu.Id,
stu.Age,
sch.sname
},"select id,age,sname from student join school on student.sid=school.sid")
But when I try to write the following statement, it's possible to throw an exception.
c#
public List Query Query(Func<T,TResult> fun,string sql)
{
return connection.Query<TResult>(sql);
}
public int Count()
{
}
//use
var list = Query((Student s)=>new
{
s.Id,
Count = Count()
},"select id,count(sid) from student")
Assuming that a bool type IsDelete field is added to the Student and the database uses bit (1), when I write the following statement, it must cause an exception.
c#
public List Query Query(Func<T,TResult> fun,string sql)
{
return connection.Query<TResul;t>(sql);
}
var list = Query((Member s)=>new
{
s.Id,
s.IsDelete
},"select id,isdelete from student")
Most importantly, I'm developing the LINQ implementation of dapper (Dapper. Common is already open source in github). Dapper's problems will make it difficult for me to carry on, and my little friends and I are very frustrated.
I acknowledge that anonymous types aren't a great fit currently; I disagree that there are "serious bugs" in this area; if you feel there are, please be very specific. We can only fix things that are clearly understood, and from the examples shown here I don't yet understand what concerns you are trying to highlight. The more specific you can be, the more we can help.
I acknowledge that anonymous types aren't a great fit currently; I disagree that there are "serious bugs" in this area; if you feel there are, please be very specific. We can only fix things that are clearly understood, and from the examples shown here I don't yet understand what concerns you are trying to highlight. The more specific you can be, the more we can help.
@
DROP TABLE IF EXISTS `member`;
CREATE TABLE `member` (
`id` int(11) NOT NULL DEFAULT '0',
`is_delete` bit(1) DEFAULT NULL,
`name` varchar(225) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT @CHARSET=utf8;
``` C#
using NUnit.Framework;
using Dapper.Common;
namespace Tests
{
public class Tests
{
[SetUp]
public void Setup()
{
DbContextFactory.AddDataSource(new DataSource()
{
ConnectionFacotry = () => new MySql.Data.MySqlClient.MySqlConnection("server=127.0.0.1;database=test;user id=root;password=1024"),
UseProxy = true
});
}
[Test]
public void Test1()
{
var content = DbContextFactory.GetDbContext();
try
{
var list = content.From<Member>()
.GroupBy(s => s.Name)
.Select(s => new
{
s.Name,
Count = MysqlFun.Count(1)//int32
});
}
catch (System.Exception e)
{
throw;
}
Assert.Pass();
}
}
public class MysqlFun
{
[Dapper.Common.Function]
public static T Count<T>(T column)
{
return default(T);
}
}
public class Member
{
[Column("id", ColumnKey.Primary, true)]
public int? Id { get; set; }
[Column("is_delete")]
public bool? IsDelete { get; set; }
[Column("name")]
public string Name { get; set; }
}
}
//sql:SELECT name AS Name,COUNT(1) AS Count FROM Member GROUP BY name
//exception:A parameterless default constructor or one matching signature (System.String Name, System.Int64 Count) is required for <>f__AnonymousType0`2[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] materialization
```
C#
var list = content.From<Member>()
.Select(s => new
{
s.Id,
s.IsDelete
});
/**
sql:SELECT id AS Id,is_delete AS IsDelete FROM Member
exception:<>f__AnonymousType0`2[[System.Nullable`1[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Nullable`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] materialization
**/
I acknowledge that anonymous types aren't a great fit currently; I disagree that there are "serious bugs" in this area; if you feel there are, please be very specific. We can only fix things that are clearly understood, and from the examples shown here I don't yet understand what concerns you are trying to highlight. The more specific you can be, the more we can help.
aren't these serious bugs? When I use entity classes, it's normal for the “Count” field to be defined as int32, but when I use anonymous types, I get an exception. There are also problems with bool's use in anonymous types, which makes me feel alarmed and frustrated. Dapper focuses on mapping but ignores anonymous types.
The problem above is that type mismatches can lead to exceptions. Another problem is that the number of parameters does not match. When I wrote "dapper.Common " SQL Server implementation class, I use paging. At this point, I will return an additional virtual column named rownumber. When I use anonymous types, the number of constructor parameters is different. This leads to exceptions, for which I wrote some extra code to solve, and it can be solved, which would not happen if anonymous types were not used. It is doubtful why anonymous types and entity types lead to different results. Obviously, "dapper" is not friendly to anonymous type support.
I don't know if the example I wrote is specific, but I think you can install "dapper. common" to reproduce the bug (I think it's a bug). Of course, the problem of inconsistent number of parameters in paging has been dealt with by "dapper. common" (I can only return the same number of fields as anonymous types).
But there are two problems objectively. First, anonymous type mapping and entity type mapping will result in inconsistent results, even if they have the same number and the same attribute type. The second problem is that the number of parameters is inconsistent. The database query returns more columns, but the anonymous type only has some attributes corresponding to it.
我不想返回这个虚拟列rownum,但这会导致异常
虽然int32到int64之间我可以通过强制类型转换来解决匿名类型属性类型不能匹配的问题,但这需要运行时,我才能知道dapper 需要什么类型。但是bool类型dapper 需要int64,而bool类型无法和int64做强制类型转换
When software fails at a task that it is expected to do: that is a bug.
When software fails at a task that is not part of something that it was ever expected to do, documented as doing, etc - and you're asking for it do support a new usage: that's a feature request.
Well, when I found out about the new app scene of "Dapper," I desperately wanted to see it in "Dapper."
------------------ 原始邮件 ------------------
发件人: "Marc Gravell"notifications@github.com;
发送时间: 2019年8月11日(星期天) 下午4:32
收件人: "StackExchange/Dapper"Dapper@noreply.github.com;
抄送: "花间岛"1448376744@qq.com; "State change"state_change@noreply.github.com;
主题: Re: [StackExchange/Dapper] I have a suggestion that I hope dapperwriters will take it seriously and implement it. (#1305)
When software fails at a task that it is expected to do: that is a bug.
When software fails at a task that is not part of something that it was ever expected to do, documented as doing, etc - and you're asking for it do support a new usage: that's a feature request.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub, or mute the thread.
These series of issues 🍿
1448376744 please remember that people do this for free - dapper is great lib but of course it will not solve all your problems - if you think that such functionality would be great nothing stops you from contributing source code with tests
I don't know if the example I wrote is specific, but I think you can install "dapper. common" to reproduce the bug (I think it's a bug). Of course, the problem of inconsistent number of parameters in paging has been dealt with by "dapper. common" (I can only return the same number of fields as anonymous types).
But there are two problems objectively. First, anonymous type mapping and entity type mapping will result in inconsistent results, even if they have the same number and the same attribute type. The second problem is that the number of parameters is inconsistent. The database query returns more columns, but the anonymous type only has some attributes corresponding to it.
1448376744 please remember that people do this for free - dapper is great lib but of course it will not solve all your problems - if you think that such functionality would be great nothing stops you from contributing source code with tests
Yes, I also wrote my own LINQ implementation dapper. Anonymous types are very common in LINQ implementations, but problems should be raised and improved.
Is there anything in this issue that isn't also covered by #1304 ? If so, can we merge them to keep everything together?
Good afternoon,
I seem to have found the cause of this problem.
``` C#
// in file:DefaultTypeMap
public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
var constructors = _type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (ConstructorInfo ctor in constructors.OrderBy(c => c.IsPublic ? 0 : (c.IsPrivate ? 2 : 1)).ThenBy(c => c.GetParameters().Length))
{
ParameterInfo[] ctorParameters = ctor.GetParameters();
if (ctorParameters.Length == 0)
return ctor;
if (ctorParameters.Length != types.Length)
continue;
int i = 0;
for (; i < ctorParameters.Length; i++)
{
if (!string.Equals(ctorParameters[i].Name, names[i], StringComparison.OrdinalIgnoreCase))
break;
if (types[i] == typeof(byte[]) && ctorParameters[i].ParameterType.FullName == "System.Data.Linq.Binary")
continue;
var unboxedType = Nullable.GetUnderlyingType(ctorParameters[i].ParameterType) ?? ctorParameters[i].ParameterType;
if ((unboxedType != types[i] && !SqlMapper.HasTypeHandler(unboxedType))
&& !(unboxedType.IsEnum && Enum.GetUnderlyingType(unboxedType) == types[i])
&& !(unboxedType == typeof(char) && types[i] == typeof(string))
&& !(unboxedType.IsEnum && types[i] == typeof(string)))
{
break;
}
}
if (i == ctorParameters.Length)
return ctor;
}
return null;
}
This line of code seems to be the reason why an anonymous type of constructor cannot match.
``` C#
if ((unboxedType != types[i] && !SqlMapper.HasTypeHandler(unboxedType))
When I copy and delete this condition, what's the bad problem?
Will it result in that when I complete the mapping through the constructor, I can't match the constructor correctly?
If that's the case, it doesn't matter. I'm not going to define constructors.
C#
SqlMapper.TypeMapProvider = (type) => new LinqTypeMap(type);
Most helpful comment
When software fails at a task that it is expected to do: that is a bug.
When software fails at a task that is not part of something that it was ever expected to do, documented as doing, etc - and you're asking for it do support a new usage: that's a feature request.