Xamarin.Forms and Entity Framework Core 2.0: CRUD Example

Sunday, August 27, 2017


I am very exiced to write this blog post. First time I seen EF was in ASPNET MVC and I fall in love with it, now when I am also very active in Xamarin Development, Entity Framework is something that I miss from my ASP.NET dev "world". With version Core 2.0 all platforms Android, iOS and UWP (uwp soon) are supported so I decided to write this blog post.

When I learn something I like to see it from zero to some CRUD operations in the app, so this blog post will be like that. We will have couple of tables (two), our context class and CRUD operations in Xamarin.Forms.

Hope that you will like it.


First of all our shared project need to be .NET Standard Library 2.0 and here is a good article about it: https://blog.xamarin.com/building-xamarin-forms-apps-net-standard/

You can also check out these great blog posts from Adam Pedley:




If you have any question about migrating to .NET Standard please comment down bellow and I will try to make special blog post about that.

Create new Xamarin.Forms app as always I will use PCL and I will migrate to the .NET Standard Library 2.0.. and add our three standard folders: Models, Views, ViewModels and additional ones are Helpers and DataAccess.
Like this:

Note: At this moment EF Core 2.0 is working on all platforms but UWP is not supporting .NET Standard 2.0 at it will be supported by the end of the year. 
More info here: https://github.com/dotnet/standard/blob/master/docs/versions.md

But when UWP become .NET Standard 2.0 "friendly" I will update this blog post.

Note #2: At this moment EF Core is not supporting lazy load.
More info here: https://github.com/aspnet/EntityFrameworkCore/issues/3797
And here is a couple of word from Rowan Miller: "Just to add one data point to the discussion. Lazy Loading isn't going to be in 2.0 but we are adding some features that are groundwork for implementing it. The biggest one is Life Cycle Hooks, which combined with the EntityEntry APIs we added in 1.1, will allow a rudimentary roll-your-own lazy loading pattern."


Community: "Entity Framework Core 2.0 is available in Xamarin.Forms to all platforms (UWP is coming very very soon)"

Me:



Ok we can start with tutorial now :

First  we need to add nuget packages to use EF in our app, in your .NET Standard class library and Android and iOS project add this nuget: Microsoft.EntityFrameworkCore.Sqlite


When you finish installing the nuget you want to add this line in iOS project in AppDelagate.cs:
Now you are ready to follow the tutorial.

I will use MVVM for this tutorial and that is my advice to you also, the main focus of this tutorial will be Entity Framework, so if anything is blurry for you about MVVM, you can checkout some of my previous tutorials and blog posts about MVVM.

First thing we need to do is to make our models, our entity models which will represent the tables in our database. For this tutorial I will use two classes/tables with one-to-many relationship with Team and Player.

These classes looks like this:

Team.cs:
and Player.cs:
That are the classes which we will use in our database.

If you are familiar with EntityFramework you will know that we need some class which will represent the context of our database.

So we need one class which will inherent from DbContext class and it will hold our two table classes with in this case two DbSet properties.

Here you can see a code snippet for our DatabaseContext and some additional code lines that will be described in the next few paragraphs:
in the constructor at line 17. We are calling the method called EnsureCreated (without it you will get an exception).

It ensures that the database for the context exists. If it exists, no action is taken. If it does not exist then the database and all its schema are created. If the database exists, then no effort is made to ensure it is compatible with the model for this context.

Also inside of DatabaseContext class we have method OnConfiguring where you can set some options for database. In this particular case we need to get sqlite database path for every platform that is used in our solution. To get these values best approach is to use DependencyService which is built in Xamarin.Forms.

Code lines for getting sqlite database path for platforms:

In this example I am using the DependencyService, you will see the whole code in github repo. I will write another blog post about DependencyService in Xamarin.Forms. If you don't want to go with DependencyService you can simply pass this string that you get from from code lines above to the App.cs in your shared project from platforms specific projects and store it in some public static string property and access it from db context. The decision is yours. 😎

Now our database is ready and we can now implement CRUD operations in our App.


BaseViewModel:

As I mentioned early I will use MVVM in this app example so first thing that I want to make is a Base-view-model which will hold the OnPropertyChanged() method implementation so it is easier to us just to inherit from it and use it with our properties in view model.

Our BaseViewModel:


READ:

Main idea in this app is to list all the teams, view details about them, add players to the team... So first view will be ListPage for our Teams.

Create new content page called TeamsListPage.xaml and it should look like this:
As you can see we have our controls ready to do binding from viewmodel.

code behind class called TeamsListPage.xaml.cs:

and the main part is our view-model:
From XAML code you can see that we have one listview and we are binding that listview to an ObservableCollection of the type Team.

We are populating this collection with list of teams from database, so in constructor of view-model we need to initialize DatabaseContext object with known linq syntax we are getting all teams from database.

Next step is to implement Create operation with Entity Framework.

CREATE:

Create new page inside of Views folder called AddTeamPage.xaml. This page is simple "form" layout with couple of entry controls for Team properties.

XAML code looks like this:
Code behind:
View-model for this page is:

We have standard binding from controls to the view-model properties, also there is one command which will trigger SaveTeam() method for the adding team to database.

That method is interesting for us.

We are creating new object of type Team, and for Team properties we are setting those from View-model which also represents the data from xaml controls (Using MVVM and Binding).

Now we are ready to add that entry to database, with standard approach using .Add(objectToInsert) method, and of course we need to commit that insert with .SaveChanges().

Now we will test this:



DELETE:

When user clicks on list view item on the TeamListPage we want to open new page called TeamDetailsPage and show basic info about this team. So let's implement that, if you scroll up you will see that in our TeamListPage we have one event for openning new page.
TeamDetailsPage XAML:

Code behind:
... and a view-model:
Code is pretty much self explanatory, most interesting part for us is DeleteTeam() method, inside of it you can see usage of Remove() method with EF.

First step is to get a an team by Id using Find() method, when we have our team to delete we can call Remove() method and as parameter send the object to remove from database, and as always commit that with SaveChanges().

Let's test this:



UPDATE:


In our TeamDetailsPage we have toolbar item for opening an EditTeamPage so there we will implement Update operations for team class/table.
XAML code:
Code-behind:
View-Model:
SaveTeam() is method where the update code is located.

First thing is to get existing team from database by Id, this is very important because we will make changes on this object and later save/update it to database.

After we have our object of type team to update, we will change its values by those from our view-model, from user input from XAML.

Now we need to save those changes with two approaches, one is to use Update and other approach is with EntityState.

Now we can test this:


It works! With this example we have completed our CRUD on Team table.

Now we can continue to do some operations with Player class/table in our db. If you followed this tutorial from start to this point you will be able to do this by yourself if you want. But I will finish this tutorial with those operations so if you want you can follow me to the end.

Add new Player:

In TeamDetailsPage you can find toolbar item for adding new player for that team, so we will use it to open new page called AddPlayerPage.xaml, and in that page we are passing the teamId just to know in which team we are adding that new player.

Xaml:
Code behind:
View Model:

SavePlayer() method will handle the adding new player to the database, inside of it we are getting the values from our viewmodel and creating new player object with that values, and for property "foreign key" TeamId we will set teamId that we passed from TeamDetailsPage.

After that we just add it to dbcontext like always, and commit that with SaveChanges().

Let's test this:

Edit Player:

... and edit is pretty same approach, only difference is that we will update it. To edit player we need to tap it on the list of player in TeamDetailsPage, we will pass the playerId to the EditPlayerPage.

Xaml:
Code-behind:
View-model:


In SavePlayer() method we are setting new values from our view to the player object that we get from database by playerId, and committing changes using SaveChanges() (nothing new).

Let's test this:



With this example we are done!

And that is it, we have our app done, we have implemented all CRUD operations using Entity Framework 2.0 with Xamarin.Forms.

Code for this example is available on the my GitHub repo more about it here:

https://github.com/almirvuk/Xamarin.Forms_EFCore


I hope this tutorial was helpful for you. My goal with this tutorial was to show CRUD examples using Entity Framework Core 2.0. If anything was blurry you can write me in the comment section down bellow. If this was helpful you can also write it, and share it with your friends.

Best regards! Almir Vuk

You Might Also Like

29 comments

  1. Hi Almir,
    Thanks for sharing tha t valueable blog post. Adam Pedley blogged about that stuff in Feb '17 and also about how to migrate an existing PCL based XF App to .NET Standard.

    https://xamarinhelp.com/entity-framework-core-xamarin-forms/

    https://xamarinhelp.com/dot-net-standard-pcl-xamarin-forms/

    Would appreciate if you could add those to links at the beginning of your blog. Thanks
    Eric

    ReplyDelete
    Replies
    1. Hi Eric,

      You are right, I just added them. :)

      Best regards!

      Delete
  2. You mention PCL a lot here. Shouldn't that just be netstandard projects? Not PCL?

    ReplyDelete
    Replies
    1. You are right, we need to migrate from PCL to .NET Standard Library which I mentioned right at the beginning, I just edited those three word where PCL is mentioned instead of .NET Standard library,

      Thank you

      Delete
  3. It will be better if you also provide a simplified version of this tutorial. Just to make sure that EFCore 2.0 works on Xamarin.Forms (excluding UWP). For example, just use a single model Player, a simple UI and a simple database operation (Add just fine). Thank you!

    ReplyDelete
    Replies
    1. You can find that kind of tutorial on Xamarin Help from Adam Pedley
      https://xamarinhelp.com/entity-framework-core-xamarin-forms/

      Best regards!

      Delete
  4. Thank you for your work on this tutorial. I have been trying to get Entity Framework to run with Xamarin for the past two weeks and now with your tutorial I finally have!
    You have saved me many more weeks of frustration, thank you.

    ReplyDelete
  5. Super job Man, Thank a lot. Was very helpful to get in with EFCore for Xamarin.

    ReplyDelete
  6. I tried to re-build your project using latest template from vs 2017 which does not use packages.config file, and when you deploy to the droid emulator i am getting this nasty error

    D/Mono ( 7808): Assembly Loader probing location: 'System.Runtime.CompilerServices.Unsafe'.
    F/monodroid-assembly( 7808): Could not load assembly 'System.Runtime.CompilerServices.Unsafe' during startup registration.

    Looks like it is still active not resolved issue. Wonder if you encountered the same issue recently using EFCore

    ReplyDelete
    Replies
    1. Have you looked here: https://github.com/aspnet/EntityFrameworkCore/issues/8922

      Delete
    2. yeah, don't feel to move back to use packages.config to fix this problem. Still acrive issue.

      Delete
    3. I agree, it seems like we will need to wait to this issue to be resolved :(

      Delete
  7. Greetings I try to execute the gintub project in visual studio 2017 and it tells me the following error
    Severity Code Description Project File Line Status suppressed
    Error NU1201 The Xamarin.Forms_EFCore project is not compatible with uap10.0.10586 (UAP, Version = v10.0.10586). The Xamarin.Forms_EFCore project supports: netstandard2.0 (.NETStandard, Version = v2.0)

    what will I be doing wrong

    ReplyDelete
    Replies
    1. I will need to update that project code and target .net standard 2.0 in uwp project.

      Delete
    2. You can also do that, or if you are not going to use UWP project you can simply unload it and use ios and android version. :)

      Delete
  8. when I think the project does not indicate the pcl option
    I create it directly with .NET Standard when I include the nugget Microsoft.EntityFrameworkCore.Sqlite ver 2.0.2 the android application stops working and sends the following error

    Assembly Loader probing location: 'System.Runtime.CompilerServices.Unsafe'.
    04-09 21: 29: 31.589 F / monodroid-assembly (3814): Could not load assembly 'System.Runtime.CompilerServices.Unsafe' during startup registration.
    04-09 21: 29: 31.589 F / monodroid-assembly (3814): This might be due to an invalid debug installation.
    04-09 21: 29: 31.589 F / monodroid-assembly (3814): A common cause is to 'adb install' the app directly instead of doing from the IDE.

    Could you please tell me what I'm doing wrong

    Thank you in advance for your response
    excuse my english language

    ReplyDelete
  9. Hello and thanks for this great blogs. I'm a beginner in programming with Xamarin and using MVVM and EF.
    I'm getting an exception on this.Database.EnsureCreated();

    Exception text is :

    Unhandled Exception:

    System.InvalidOperationException: A suitable constructor for type 'Microsoft.EntityFrameworkCore.Internal.DiagnosticsLogger`1[Microsoft.EntityFrameworkCore.DbLoggerCategory+Infrastructure]' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor. occurred

    I have no clue :-/

    Can you give me a hint please ?

    THanks :-)

    ReplyDelete
  10. regards

    I was able to execute the example without any problem, thank you very much for sharing this very well-prepared example. Congratulations

    What other samples would you recommend to continue learning

    ReplyDelete
  11. Thank you very much for this guide :)

    ReplyDelete
  12. Thanks for this great tutorial. Hoping you could also make tutorial with dependency injection.

    ReplyDelete
    Replies
    1. That is also possible :) Thank you for reading my blog :)

      Delete
  13. Hey Almir, thank you for this great tutorial. I learned so many new things but I was wondering is it possible to see tables of database like the whole database?

    ReplyDelete
  14. It was really a nice post and I was really impressed by reading this .NET Online Course

    ReplyDelete
  15. Thanks for this blog!

    However, I have tried running the android application on Xamarin Live Player App on my phone and it comes up with an error of unhandled exception. Is this due to the config of the SQL database. How do I set this configuration of packages.config?

    ReplyDelete
    Replies
    1. I am not sure what do you think by that, can you please explain your issue again? Thanks!

      Delete
  16. Nice job man!
    But how can I implement M:N relation?

    ReplyDelete