Xamarin-android: Application using EF Core 2.1.1 with SdkOnly linking crashes due to duplicate values returned by GetMethod

Created on 23 Jul 2018  路  13Comments  路  Source: xamarin/xamarin-android

This was previously mentioned in https://github.com/xamarin/xamarin-android/issues/1813#issuecomment-400888600 and reported by multiple customers in the EF Core repo at https://github.com/aspnet/EntityFrameworkCore/issues/12460. I am copying some details in this issue but feel free to find more details and reach out to customers hitting it in those links.

I am forwarding the issue to Xamarin because the only plausible root cause seems to be that reflection is returning the same MethodInfo for different overloads of a method (which doesn't seem to make much sense) and given we don't have the Xamarin expertise we need someone to investigate if this is a bug or otherwise give us advice if we are doing something wrong.

In summary, the code that causes the exception is doing something like this:

``` c#
var supportedMethods = new Dictionary
{
{ typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(double) }), "abs" },
{ typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(float) }), "abs" },
{ typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(int) }), "abs" },
{ typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(long) }), "abs" },
{ typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(sbyte) }), "abs" },
{ typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(short) }), "abs" },...


That causes `System.ArgumentException: An item with the same key has already been added. Key: Int32 Abs(Int32)`, which seems to indicate that the MethodInfo returned for Math.Abs(int32) is the same as either Math.Abs(double) or Math.Abs(float), which doesn't make much sense.

We already suggested adding Math.Abs to LinkDescription.xml (in case GetMethod is just returning null because the actual code was removed by the linker) but customers report that this workaround does not help.

### Steps to Reproduce

1. Create a project that uses Microsoft.EntityFrameworkCore.SqlLite. A repro project was provided at https://github.com/aspnet/EntityFrameworkCore/issues/12460#issuecomment-403451697. 
2. Build the project and link it with <AndroidLinkMode>SdkOnly</AndroidLinkMode>
3. Run the application

### Expected Behavior
Application runs.

### Actual Behavior
Application crashes with:

Exception message:
Stack trace:
06-25 16:48:31.244 9279 9279 I MonoDroid: UNHANDLED EXCEPTION:
06-25 16:48:31.257 9279 9279 I MonoDroid: System.TypeInitializationException: The type initializer for 'Microsoft.EntityFrameworkCore.Sqlite.Query.ExpressionTranslators.Internal.SqliteMathTranslator' threw an exception. ---> System.ArgumentException: An item with the same key has already been added. Key: Int32 Abs(Int32)
06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Collections.Generic.Dictionary2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) <0xceeb8b14 + 0x0045c> in <c099d544051e40b89a67a87a43581f01>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Collections.Generic.Dictionary2[TKey,TValue].Add (TKey key, TValue value) <0xceeb7fd0 + 0x00013> in :0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Sqlite.Query.ExpressionTranslators.Internal.SqliteMathTranslator..cctor () <0xcd753afc + 0x00207> in <135a24207446461281bfc2c90f71e590>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: --- End of inner exception stack trace ---
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.RelationalCompositeMethodCallTranslator+<>c__DisplayClass5_0.b__0 (Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.IMethodCallTranslator translator) <0xcd61f2dc + 0x00044> in :0
06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Linq.Enumerable+SelectListIterator2[TSource,TResult].MoveNext () <0xce42d194 + 0x000ff> in <dd44b4af145c4bd6a0a60da9e4b5131f>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) <0xce415f5c + 0x000f3> in <dd44b4af145c4bd6a0a60da9e4b5131f>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) <0xce415c6c + 0x0003f> in <dd44b4af145c4bd6a0a60da9e4b5131f>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.RelationalCompositeMethodCallTranslator.Translate (System.Linq.Expressions.MethodCallExpression methodCallExpression, Microsoft.EntityFrameworkCore.Metadata.IModel model) <0xcd61ef6c + 0x002bf> in <b4c4c93ef655443999d2211e0c2e61cd>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.VisitMethodCall (System.Linq.Expressions.MethodCallExpression methodCallExpression) <0xcd614aac + 0x00393> in <b4c4c93ef655443999d2211e0c2e61cd>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Linq.Expressions.MethodCallExpression.Accept (System.Linq.Expressions.ExpressionVisitor visitor) <0xce4a5000 + 0x0001b> in <dd44b4af145c4bd6a0a60da9e4b5131f>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Linq.Expressions.ExpressionVisitor.Visit (System.Linq.Expressions.Expression node) <0xce49f890 + 0x00027> in <dd44b4af145c4bd6a0a60da9e4b5131f>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Remotion.Linq.Parsing.ThrowingExpressionVisitor.Visit (System.Linq.Expressions.Expression expression) <0xce62b070 + 0x0006b> in <1081ac98085b4c0b96c42f3872e13655>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.SqlTranslatingExpressionVisitor.Visit (System.Linq.Expressions.Expression expression) <0xcd613b00 + 0x0010f> in <b4c4c93ef655443999d2211e0c2e61cd>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitWhereClause (Remotion.Linq.Clauses.WhereClause whereClause, Remotion.Linq.QueryModel queryModel, System.Int32 index) <0xcd5f7064 + 0x000ef> in <b4c4c93ef655443999d2211e0c2e61cd>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Remotion.Linq.Clauses.WhereClause.Accept (Remotion.Linq.IQueryModelVisitor visitor, Remotion.Linq.QueryModel queryModel, System.Int32 index) <0xce63c7cc + 0x00093> in <1081ac98085b4c0b96c42f3872e13655>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses (System.Collections.ObjectModel.ObservableCollection1[T] bodyClauses, Remotion.Linq.QueryModel queryModel) <0xce62e964 + 0x00167> in <1081ac98085b4c0b96c42f3872e13655>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel (Remotion.Linq.QueryModel queryModel) <0xce62e468 + 0x0006b> in <1081ac98085b4c0b96c42f3872e13655>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.VisitQueryModel (Remotion.Linq.QueryModel queryModel) <0xce6e2e08 + 0x00047> in <1a963d6bdb8d435e8dcdc28935e050ad>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor.VisitQueryModel (Remotion.Linq.QueryModel queryModel) <0xcd5f5da0 + 0x0005f> in :0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.CreateQueryExecutor[TResult] (Remotion.Linq.QueryModel queryModel) <0xce6e0fcc + 0x00177> in <1a963d6bdb8d435e8dcdc28935e050ad>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult] (Remotion.Linq.QueryModel queryModel) <0xce6c8964 + 0x000bb> in <1a963d6bdb8d435e8dcdc28935e050ad>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult] (System.Linq.Expressions.Expression query, Microsoft.EntityFrameworkCore.Query.Internal.IQueryModelGenerator queryModelGenerator, Microsoft.EntityFrameworkCore.Storage.IDatabase database, Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger1[TLoggerCategory] logger, System.Type contextType) <0xce70f75c + 0x0028f> in <1a963d6bdb8d435e8dcdc28935e050ad>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass13_01[TResult].b__0 () <0xce71037c + 0x0005b> in <1a963d6bdb8d435e8dcdc28935e050ad>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc] (System.Object cacheKey, System.Func1[TResult] compiler) <0xce6f70ac + 0x000c3> in <1a963d6bdb8d435e8dcdc28935e050ad>:0 06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult] (System.Object cacheKey, System.Func1[TResult] compiler) <0xce6f7024 + 0x0003b> in <1a963d6bdb8d435e8dcdc28935e050ad>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult] (System.Linq.Expressions.Expression query) <0xce70f47c + 0x001a7> in <1a963d6bdb8d435e8dcdc28935e050ad>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult] (System.Linq.Expressions.Expression expression) <0xce6f7b58 + 0x00047> in <1a963d6bdb8d435e8dcdc28935e050ad>:0
06-25 16:48:31.257 9279 9279 I MonoDroid: at System.Linq.Queryable.FirstOrDefault[TSource] (System.Linq.IQueryable`1[T] source) <0xce4096f4 + 0x000cb> in :0
```

Version Information

EF Core version: 2.1.1
Xamarin Andriod version not specified in original report

bug

Most helpful comment

Source code in the EF Core provider for SQLite that is causing the exception can be found at

https://github.com/aspnet/EntityFrameworkCore/blob/f3a183efd51c9dda512b8af9a4274b36b7c1450c/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteMathTranslator.cs#L17-L47

I can confirm that this code was modified in 2.1.1.

All 13 comments

Source code in the EF Core provider for SQLite that is causing the exception can be found at

https://github.com/aspnet/EntityFrameworkCore/blob/f3a183efd51c9dda512b8af9a4274b36b7c1450c/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteMathTranslator.cs#L17-L47

I can confirm that this code was modified in 2.1.1.

@pierceboggan customers are blocked of using the latest version of EF Core with Xamarin because of this. Any chance we can get someone to take a look soon?

@luhenry, @radekdoulik: This bug seems weird.

See also:
https://github.com/aspnet/EntityFrameworkCore/issues/12460#issuecomment-404988910

Since it is saying that Abs(int32) is a duplicate key, that means that either typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(double) }) or typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(float) }) returned the same method info as typeof(Math).GetMethod(nameof(Math.Abs), new[] { typeof(int) }), which seems very unexpected.

I can confirm the behavior outlined in the reproduction steps on Xamarin.Android 8.3.3.2:

07-26 15:56:50.903 29686-29686/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: Issue12460.Issue12460, PID: 29686
    android.runtime.JavaProxyThrowable: System.TypeInitializationException: The type initializer for 'Microsoft.EntityFrameworkCore.Sqlite.Query.ExpressionTranslators.Internal.SqliteCompositeMethodCallTranslator' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Microsoft.EntityFrameworkCore.Sqlite.Query.ExpressionTranslators.Internal.SqliteMathTranslator' threw an exception. ---> System.ArgumentException: An item with the same key has already been added. Key: Double Abs(Double)

However, the behavior does not exhibit on Xamarin.Android 9.0.0.15. Perhaps the bump to Mono 5.12 resolved this issue upstream @jonpryor ?

@divega Have you tried 15.8 Previews(4 or 5) with this issue? I can't seem to reproduce there.

@JonDouglas, @smitpatel and I actually did not repro the issue but we assumed we were missing something. Also, customers that reported the issue at https://github.com/aspnet/EntityFrameworkCore/issues/12460 did not specify what version of Xamarin.Android they were using (or at least I didn't see it).

I will go ahead and copy your question to the EF Core issue to see if they respond.

I'm not able to build my app on 15.8 Preview 5 at all, there are too many strange errors like
"PROGUARD : warning : class [.../R$anim.class] unexpectedly contains class [....R$anim]
PROGUARD : warning : there were 18 classes in incorrectly named files."

not to mention a lot of conflicts between Mono 8.1 and Mono 9, so I sadly can't tell more.

EDIT:
After disabling ProGuard and doing some adjustments to the project I was finally able to build it and it worked, so I can confirm, that there is no EF Core Error on 15.8 Preview 5.
Though there are several other Xamarin Issues that appear on that version, so it's not a solution for me and I hope the fix can be included in the next 15.7 Release as soon as possible.

@daniels7

ProGuard warnings are typically ignorable in certain cases. Since I don't have the full context to these warnings you're experiencing, I cannot speak fully on how to workaround them. Could you please create a new issue for this following our Bug Report guidelines?

As for the "several other Xamarin issues", I would also need more context so I can understand further. Can you also file an issue for each of those items in this repository?

Thanks in advance!

@JonDouglas are there any plans to have Mono Xamarin.Android 8 serviced, or is Mono Xamarin.Android 9 the way forward for all customers using the existing bits?

If there is any possibility of servicing I think it would be great to identify the root cause of this issue and then you can asses if it is something that should be fixed in a servicing release.

@divega: I don't know what "Mono 8.1" is, nor do I know what "Mono 9" is.

Do you mean Xamarin.Android 8.1 (released with Visual Studio 15.5) and Xamarin.Android 9 (to be released with Visual Studio 15.8)? If so, Xamarin.Android 8.1 uses Mono 5.4, while Xamarin.Android 9.0 uses Mono 5.12. The git diff for mono between those commits is huge, 2357 commits between them.

Visual Studio 15.5 is not getting any further service releases. 15.5 stopped getting service releases once 15.6 became stable, and 15.6 stopped getting service releases once 15.7 became stable, and...

Also, why are warning messages producing errors? That sounds odd.

I don鈥檛 know what 鈥淢ono 8.1" is, nor do I know what "Mono 9"

Yup, I only copied & pasted what @daniels7 said without checking that it was correct. Sorry about that. Thanks for the information on servicing. Then I will close the issue on the EF Core repo saying that the root cause is unknown but the issue is fixed in the upcoming Xamarin.Android 9. Is there an ETA for the release?

A disadvantage of not knowing the root cause is that we cannot provide any more workarounds than reverting to an older version of EF Core. I wasn鈥檛 thinking you would find it through examining a diff, but rather doing some debugging using the simplified repro :smile:

15.8 has been released as of yesterday and confirming from https://github.com/aspnet/EntityFrameworkCore/issues/12460#issuecomment-409390743 that Xamarin.Android 9.0 resolved this issue, I will be closing this issue as well. Thank you for the reports and patience! For those using Visual Studio for Mac, Xamarin.Android is currently in the Beta channel and will be included in a future release.

I'm not sure if this is the same issue, but even with targeting v9.0 I am getting

The type initializer for Microsoft.EntityFrameworkCore.Sqlite.Query.ExpressionTranslators.Internal.SqliteCompositeMethodCallTranslator threw an exception

In case anyone hits a similar exception but on Microsoft.EntityFrameworkCore.Sqlite.Query.ExpressionTranslators.Internal.SqliteComposteMethodCallTranslator, the workaround for that one is to add a LinkDescription.xml file as described at https://github.com/xamarin/xamarin-android/issues/2620#issuecomment-456447322.

Was this page helpful?
0 / 5 - 0 ratings