Entity Framework Core with Xamarin.Forms

With the release of Entity Framework Core 2.0, you can now run EF with a SQLite database on iOS, Android and UWP. For those coming from server or desktop development, this will mean a very easy transition to mobile database development.

Project Setup

You must have .NET Core SDK 2.0 installed, and your class library must be set to use .NET Standard 2.0.

Install Microsoft.EntityFrameworkCore.Sqlite in every project, the traditional and the class library. It will install all other required dependencies, as appropriate. You are now ready to get coding. I have an example repo, EFXamarin on GitHub if you want to see a completed solution.

Note: Do NOT add the SQLite extension in UWP, this is not needed with EF Core and will cause a conflict, if added.

Converting PCL to .NET Standard Library

If you have a PCL, a quick way to convert it to a .NET Standard Library, is to edit the csproj of this PCL. Delete everything inside, and replace it with this.

Now reload your project, and add back in your Nuget packages and references. It’s easier to wipe them all out and add them again, rather than manually doing it.

Native Project Setup

All you need to do in each platform, is get the path to the SQLite database. This is slightly different in each platform. You will need to pass this value into the class library, and that approach is up to your existing architecture. For simplicity sake, I will just pass this through the constructor of the App.cs.

Note: EFCore 1.0 with Mono 5.0+ will work on all platforms. EFCore 2.0 with Mono 5.0+ will work on all platforms except UWP . But only because support for .NET Standard 2.0 in UWP is still in the works, hence you must wait for that support, and then UWP will work with EFCore 2.0.

If you run any Mono Version lower than 5.0, you will get the following error, in iOS, if using an older version of EF Core. To use EF Core 2.0 you need at least Mono 5.2, hence you need to ensure you have installed Visual Studio 15.3 or higher.

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotImplementedException: Interpreter of ref types
at Microsoft.Scripting.Interpreter.LightCompiler.CompileMethodCallExpression (System.Linq.Expressions.Expression expr) [0x00089] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.114/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs:1283
at Microsoft.Scripting.Interpreter.LightCompiler.CompileNoLabelPush (System.Linq.Expressions.Expression expr) [0x001ba] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.114/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs:1642
at Microsoft.Scripting.Interpreter.LightCompiler.Compile (System.Linq.Expressions.Expression expr) [0x00008] in /Library/Fra
meworks/Xamarin.iOS.framework/Versions/10.4.0.114/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs:1729
etc...

XAMARIN WEEKLY NEWSLETTER

Subscribe to a hand-picked round up of the best Xamarin development links every week. Published every Friday. Free.

Is it possible and so easy to work with database first approach. I have existing sqlite db which I want to use and not to write my own classes and to create the tables again. Is it possible to load the tables like in asp.net mvc like entities ?

If the database and table already exists, it won’t overwrite it. Thats what the EnsureCreated does. The only difference is you will have to have your db in your app, and ensure its outputted to the mobile device in the correct location when they first run the app.

Yes, just use it as you normally would with Code First. You could technically remove EnsureCreated I think because it will already be there, but it leaves the creation of the db entirely up to you. I have tried leaving out the EnsureCreated before, so give it a test first, it might also do other things in the background I am not aware of.

Unfortunately, I know nothing further than what is publicly stated. I would be looking out for Xamarin Cycle 10 with Mono 5.0 which will include the CoreFX upgrade, this may resolve it but its just speculation, it could require a completely separate fix.

Thanks for the excellent post, Adam. In our Xamarin.Forms PCL project, we are using SQLite local storage and connecting to a PostgreSQL external database from which to pull data into local storage. What would your advice be in terms of navigating the flow from the external database to the local one? At this point it seems best to use sqlite-net-pcl for the local db. Would you use a different Nuget package to connect on the PostgreSQL side and then translate the data to be sqlite-net-pcl compatible so as to store it locally?

There would be nothing avail that does this automatically. If you are connecting directly to the PostgreSQL over the internet, I would suggest you instead build an API to service the requests, you shouldn’t directly expose your DB to mobile clients.

From here you would have to develop your own Syncing process. You might want to look at Azure Mobile Client, which includes syncing, but I am not about its capability to connect it up to an existing external source.

XAML and EF are completely separate. EF just gets the data and then you pass it to properties in your ViewModel to be bound to the XAML elements, such as a ListView. If you need an example of a project using XAML, you can have a look at my example with MVVMLight (https://github.com/adamped/xarch-starter)

I have downloaded your MVVMLight example however, I cannot see any references to Entity Framework in it. Furthermore I couldn’t get it to build as there are a couple of dll’s missing: APiRepositorry and DataService.

I am still interested in a simple XAML based Entity Framework example though.

I don’t have any examples of EF with XAML. They are two different parts of the system. You can just create an app using XAML and then connect up a datastore with EF. It would be best to have a XAML based app, then copy and paste over the relevant code from the EF sample to get what you want.

If you are getting an error with the Path, it means that the dbPath string isn’t getting passed through to the DataContext is null. Check that you are getting a value from the native platform when its passed through.

Thanks for the interesting post. What are your views on EF vs something like Akavache?

Also, any thoughts on corner-case issues such as your app going to sleep (and eventually being terminated) or a reboot/power-loss in the middle of DB operations corrupting your local DB? I haven’t seen much on db transactions when researching which data approach is best for my apps.

EF is an far more powerful ORM, with more features than Akavache. I don’t know of what performance enhancements they make with EF, but I assume over time they will continue to tune it.

Akavache is made by Paul Betts, but I don’t think there is very much active development on it anymore. Its perfect for temporary local storage, based on key-value pair. Its not good for a full relational local database.

Both Akavache and EF will support transactions. Hence power loss or reboot shouldn’t be a big deal, if you use transaction for all writes to the DB. Akavache does by default, I think you might have to manually do it in EF.

Would it be possible for EF Core and Azure Sync (MobileServiceAzureClient) to work together? If yes, who would create the local db and sync it to azure? Is it EF (code-first) or is it the azure client? I am quite confused of which ever to use, or would it be better for me to just use Azure Client? Thanks!

It wouldn’t be easy to use both, because you need to use the SDK to communicate with the database, which will add and maintain additional sync values. You could possibly do it, using both, but you would need to understand the table structures below and generate your own LastUpdated, Deleted and Version information, when you updated rows.

Thanks, I checked and browsed through the synchronization api, that’s the other option I am thinking of.

I just have one clarification for this one, but then if I use the Azure SDK, wouldn’t it be pointless for me to use EF as it would add additional complexity? So wouldn’t be the best choice is to use Azure SDK (as it currently supports .net standard now)?

Right now, from what I can see, using EF would be easier if I have my own sync api, which then the datas resides on premise, else, Azure if I want data to be resided on azure.

You can use your own Sync API and put it on Azure, as well. The Azure Mobile Client just uses Azure Tables I think, though you might be able to put in on SQL as well. I did previously, but I had to create the tables myself back in the day.

But lets frame this a different way. If you have a simple data store, and want a quick and easy way to do simple sync to a remote data store on Azure, then Azure Mobile Client is the way to go.

If you have a complex sync process or data store and want solid control over it. Roll your own sync api and use EF or sqlite-pcl-net.

I’ll add it to my list. I haven’t used Realm before, though SQLite and Realm have comparable performance in most areas. I would think that EF would have greater capabilities in terms of an ORM, but I am not sure what performance hit you might take for using EF.

Really nice article!
Could you elaborate about db migrations ?
What does happen when the Android version code is increased (when the app is updated)? Same question for iOS which I know less.
Do we have a callback to manage migrations or does EF does it for us?
Thanks a lot

Alright I will have a look at the official documentation. I thought there would be specific behaviour because of mobile concerns and upgrades. Thank you and I’m glad you will write an article about it sometime.