sqlite-net
sqlite-net copied to clipboard
why we can't use type `struct` as the table data type while using nuget sqlite-net-pcl 1.8.116
If I used type struct
as the table data type,I could create and insert some items into my database ,but if I queried the items from the database, my app throws an error System.ArgumentException Message=method arguments are incompatible
.
I could reproduce this problem with nuget sqlite-net-pcl 1.8.116
., but if I used lower version (e.g. 1.7.335), there is no such error.
You can try to repreduce this problem with official sample here: https://docs.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/todo/
Steps:
1.Try to create a new Model with type struct
;
2.replace class TodoItem
with the new model we create above, in page TodoListPage.xaml.cs
, the app will try to add a new item in function OnItemAdded
3.Aftern inserting a new item, if we come back to page TodoListPage
, the function OnAppearing()
which will read back the new added item. Here the app will throw such error.
I have this too., but only noticed now. Rolling back to 1.7.335 makes it work again. Should I update my struct to class?
I also have the same issue in Unity editor switched to Android platform. When I use struct for the data, I get following error:
ArgumentException: method arguments are incompatible
System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, System.Boolean throwOnBindFailure, System.Boolean allowClosed) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method) (at <695d1cc93cca45069c528c15c9fdd749>:0)
SQLite.FastColumnSetter.CreateTypedSetterDelegate[ObjectType,ColumnMemberType] (SQLite.TableMapping+Column column, System.Func3[T1,T2,TResult] getColumnValue) (at Assets/_ThirdParty/Runtime/SQLite/SQLite.cs:3575) SQLite.FastColumnSetter.CreateNullableTypedSetterDelegate[ObjectType,ColumnMemberType] (SQLite.TableMapping+Column column, System.Func
3[T1,T2,TResult] getColumnValue) (at Assets/_ThirdParty/Runtime/SQLite/SQLite.cs:3562)
SQLite.FastColumnSetter.GetFastSetter[T] (SQLite.SQLiteConnection conn, SQLite.TableMapping+Column column) (at Assets/_ThirdParty/Runtime/SQLite/SQLite.cs:3400)
SQLite.SQLiteCommand+<ExecuteDeferredQuery>d__121[T].MoveNext () (at Assets/_ThirdParty/Runtime/SQLite/SQLite.cs:3029) System.Collections.Generic.List
1[T]..ctor (System.Collections.Generic.IEnumerable1[T] collection) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Linq.Enumerable.ToList[TSource] (System.Collections.Generic.IEnumerable
1[T] source) (at <351e49e2a5bf4fd6beabb458ce2255f3>:0)
SQLite.SQLiteCommand.ExecuteQuery[T] () (at Assets/_ThirdParty/Runtime/SQLite/SQLite.cs:2975)
SQLite.SQLiteConnection.Query[T] (System.String query, System.Object[] args) (at Assets/_ThirdParty/Runtime/SQLite/SQLite.cs:1007)
SQLite version: v1.8.116 from 3 September 2021
Changing the struct to sealed class fixes the issue.
这是因为FastColumnSetter中的CreateTypedSetterDelegate函数调用了Delegate.CreateDelegate. 当第一个类型是Value类型时,CreateDelegate会失败.
// 当ObjectType 是Value类型时,无法创建Delegate
var setProperty = (Action<ObjectType, ColumnMemberType>)Delegate.CreateDelegate (
typeof (Action<ObjectType, ColumnMemberType>), null,
column.PropertyInfo.GetSetMethod ());
return (o, stmt, i) => {
var colType = SQLite3.ColumnType (stmt, i);
if (colType != SQLite3.ColType.Null)
setProperty.Invoke ((ObjectType)o, getColumnValue.Invoke (stmt, i));
};