sqlite-net icon indicating copy to clipboard operation
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

Open jessiezh0320 opened this issue 3 years ago • 3 comments

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.

jessiezh0320 avatar Oct 27 '21 03:10 jessiezh0320

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?

bobwhitten avatar Feb 09 '22 21:02 bobwhitten

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.Func3[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.List1[T]..ctor (System.Collections.Generic.IEnumerable1[T] collection) (at <695d1cc93cca45069c528c15c9fdd749>:0) System.Linq.Enumerable.ToList[TSource] (System.Collections.Generic.IEnumerable1[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.

gindemit avatar Mar 29 '22 15:03 gindemit

这是因为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));
            	};

duanrui71 avatar Feb 28 '23 17:02 duanrui71