0

I try to experiment with new platform for me, Xamarin Forms. Based on .Net Core and EF Core knowledge I decided to begin with injecting Sqlite ORM service (sqlite-net-pcl) in Xamarin Forms Shell template included in Visual Studio 2019. In this template there is already implemented Mock CRUD service based on in-memory data structure so I wanted to implement my own service and inject it with DependencyService. At first I have modified data model with needed attribute:

public class Item
{
    [PrimaryKey, AutoIncrement]
    public string Id { get; set; }
    public string Text { get; set; }
    public string Description { get; set; }
}

Next I implemented CRUD service:

public class SqliteDataStore : IDataStore<Item>
{
    private readonly SQLiteConnection _db;

    public SqliteDataStore()
    {
        _db = new SQLiteConnection(Path.Combine(FileSystem.AppDataDirectory, "items.sqlite"));
        _db.CreateTable<Item>();
        if (_db.Table<Item>().Count().Equals(0))
        {
            _db.InsertAll(new List<Item>
            {
                new Item { Id = Guid.NewGuid().ToString(), Text = "First item", Description = "This is the first item description." },
                new Item { Id = Guid.NewGuid().ToString(), Text = "Second item", Description = "This is the second item description." },
                new Item { Id = Guid.NewGuid().ToString(), Text = "Third item", Description = "This is the third item description." }
            }
            );
        }
    }

    public async Task<bool> AddItemAsync(Item item)
    {
        _db.Insert(item);
        return await Task.FromResult(true);
    }

    public async Task<bool> DeleteItem(string id)
    {
        _db.Delete<Item>(id);
        return await Task.FromResult(true);
    }

    public async Task<Item> GetItemAsync(string id)
    {
        return await Task.FromResult(_db.Get<Item>(id));
    }

    public async Task<IEnumerable<Item>> GetItemsAsync(bool forceRefresh = false)
    {
        return await Task.FromResult(_db.Table<Item>().ToList());
    }

    public async Task<bool> UpdateItemAsync(Item item)
    {
        _db.Update(item);
        return await Task.FromResult(true);
    }
}

Next I changed injected service in App class:

public App()
{
    InitializeComponent();

    DependencyService.Register<SqliteDataStore>();
    MainPage = new AppShell();
}

This implementation properly works with EF Core in Xamarin Forms but EF Core is very slow so I changed ORM (sqlite-net-pcl) and it does not work.

1 Answers1

1

In the document of dependency servicee, it says:

Important

Registration with the Register methods must be performed in platform projects, before the functionality provided by the platform implementation is invoked from shared code.

So, I think you have added the line DependencyService.Register<SqliteDataStore>(); at a wrong place.

Solution:

For example, in iOS it should be:

[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        global::Xamarin.Forms.Forms.Init();
        LoadApplication(new App());

        DependencyService.Register<SqliteDataStore>();

        return base.FinishedLaunching(app, options);
    }
}

In Android:

protected override void OnCreate(Bundle savedInstanceState)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;

    base.OnCreate(savedInstanceState);

    DependencyService.Register<SqliteDataStore>();


    Xamarin.Essentials.Platform.Init(this, savedInstanceState);
    global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
    LoadApplication(new App());
}

There is also documents about Store Data in a Local SQLite.NET Database and Using SQLite.NET with Android you can refer.

nevermore
  • 15,432
  • 1
  • 12
  • 30
  • As I have mentioned, I had implemented this using EF Core and it works but EF Core is too "heavy" for mobile app.Registration can be done by method or attribute. Attribute registration can only be used to register platform-specific implementation. In documentation the word "CAN" is used. Not "MUST". Tomorrow I will clean-up my EF Core solution, publish it to github and paste link here – Marek Słowikowski Oct 30 '19 at 06:08
  • @MarekSłowikowski Yes, but I does not see the Attribute registration you use in the DependencyService. Let me try your code and I will update you later. – nevermore Oct 30 '19 at 06:13
  • @MarekSłowikowski I just test your code and it all works well on my side. The only thing I changed is change the Id to int type. I uploaded a sample project [here](https://github.com/XfHua/DB-sample) and you can check it. Let me know if it works for you. – nevermore Oct 30 '19 at 07:31
  • Thank you. It seems I was not enough attentive. "Looking at big things we do not see the details". – Marek Słowikowski Oct 30 '19 at 16:05
  • Yes, with your help. Thank you. – Marek Słowikowski Oct 31 '19 at 01:54
  • @MarekSłowikowski Can you please mark this answer if it is helpful to you:)? – nevermore Oct 31 '19 at 02:02