activa / iridium

Iridium - Lightweight .NET ORM for mobile, desktop and server applications
MIT License
22 stars 8 forks source link

How to use Iridium as a shared cross-platform database solution in Xamarin #7

Closed nologinatgit closed 6 years ago

nologinatgit commented 6 years ago

I have the following architecture:

I intend to use Iridium as the database provider in the shared project. I added the Iridium NuGet package to the .Net Standard project and the Xamarin.Android project, and they compiled normally.

After reading the documentation, I added the Iridium.Db.SQLite package to both projects, and tried to create the context with the following code in the shared .Net Standard project:

 public class MyIridiumContext : SqliteContext
  {
    public MyIridiumContext () : base(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "myIridium.db"))
    {
    }

    public IDataSet<Family> Family { get; set; }
  }

Now, when I try to compile, I get the following error in the Xamarin Android project:

Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'Iridium.DB.Sqlite.Win32, Version=2.2.0.0, Culture=neutral, PublicKeyToken='. Perhaps it doesn't exist in the Mono for Android profile? File name: 'Iridium.DB.Sqlite.Win32.dll' at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Resolve(AssemblyNameReference reference, ReaderParameters parameters) at Xamarin.Android.Tasks.ResolveAssemblies.AddAssemblyReferences(DirectoryAssemblyResolver resolver, ICollection`1 assemblies, AssemblyDefinition assembly, Boolean topLevel) at Xamarin.Android.Tasks.ResolveAssemblies.Execute(DirectoryAssemblyResolver resolver)

I also get a warning about the targeted project:

Package 'iridium.db.sqlite 2.2.1.530' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETStandard,Version=v2.0'. This package may not be fully compatible with your project.

Does this mean that I have to implement a context in each platform and lose the shared code? Can I create a really cross-platform solution with Iridium?

spiff123 commented 6 years ago

I tried the same with a PCL instead of a .net standard shared project and this works. I guess the iridium nuget is missing .net standard support - would be nice if this can be added.

activa commented 6 years ago

It works the same in PCL and .NETStandard projects.

If you're using Iridium in a mobile app that has a shared library (like you would with Xamarin Forms for example), the Sqlite data provider should be instantiated in the platform-specific projects, not in the shared library. There are several ways this can then be done, but the easiest way is to use dependency injection.

In your platform-specific projects:

ServiceRepository.Register(new SqliteDataProvider(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "myIridium.db"));

In your shared project, you define the context like this:

public class MyIridiumContext : StorageContext
  {
    public MyIridiumContext (IDataProvider provider) : base(provider)
    {
    }

    public IDataSet<Family> Family { get; set; }
  }

To use the context:

var context = ServiceRepository.Get<MyIridiumContext>();
spiff123 commented 6 years ago

So the point is the "new SqliteDataProvider" has to be placed in the platform specific project (iOS/Android) so that the correct sqlite dll is pulled (in the .net standard assembly it pulls alway the sqlite win32 dll...)

Shouldn't there be a register call for "MyIridiumContext" in the snippet above - and a Path.Combine as parameter to SqliteDataProvider.

It works - thanks for the hint!

There are still 2 warnings left:

xy.csproj: Warning NU1603: iridium.db.sqlite 2.2.1.530 depends on iridium (>= 2.2.1) but iridium 2.2.1 was not found. An approximate best match of iridium 2.2.1.530 was resolved. (NU1603)

xy.csproj: Warning NU1701: Package 'iridium.db.sqlite 2.2.1.530' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETStandard,Version=v2.0'. This package may not be fully compatible with your project. (NU1701)

The second one brought me to the question if the nuget can be repackaged..

activa commented 6 years ago

You can ignore the first warning. The 2nd warning is because you referenced iridium.db.sqlite in the shared project. It should only reference the iridium package.

As for your ServiceRepository comment: you're right. If you use ServiceRepository.Get<MyIridiumContext>(), you should register it first by calling ServiceRepository.Register<MyIridiumContext>(). If you call ServiceRepository.Create<MyIridiumContext>(), registering the class is not required but it will create a new context every time you call Create() instead of reusing a single instance.

spiff123 commented 6 years ago

Changed the shared/.net standard dependency to iridium and both warnings are gone. Great - thanks!

spiff123 commented 6 years ago

@nologinatgit sorry for capturing your issue

activa commented 6 years ago

See also http://iridiumdb.com/docs/iridium/multiplatform