1

I'm trying to change from SQLite to Realm.io in my Xamarin projects, but can't find any autoincrement on ID's. I found a post with Java, with following line:

int nextID = (int) (realm.where(dbObj.class).maximumInt("id") + 1);

In Xamarin there isn't a where, but i tried this:

realm.All<DebitorPlateDBModel> ().Max (x => x.Id + 1);

Sadly "Max" isn't support.

Has anyone succeed on this?

SushiHangover
  • 73,120
  • 10
  • 106
  • 165

3 Answers3

2

There are different ways of achieving this, it just depends on what fits your model the best, here are a just a couple:

Test Model:

public class IdIntKeyModel : RealmObject
{
    [Indexed]
    public int ID { get; set; }
    public string Humanized { get; set; }
}

Gap-less key ordering (via Count):

Note: Good for initial bulk imports

Note: Assumes only one thread adding records and you do not have gaps in your record ids, i.e. no deletes without reordering keys, etc...

var config = RealmConfiguration.DefaultConfiguration;
config.SchemaVersion = 1;
using (var theRealm = Realm.GetInstance("StackoverFlow.realm"))
{
    var key = theRealm.All<IdIntKeyModel>();
    theRealm.Write(() =>
    {
        for (int i = 1; i < 1000; i++)
        {
            var model = theRealm.CreateObject<IdIntKeyModel>();
            model.ID = key.Count() + 1;
            model.Humanized = model.ID.ToWords();
            System.Diagnostics.Debug.WriteLine($"{model.ID} : {model.Humanized}");
        }
    });
    var whatIsTheKey = theRealm.All<IdIntKeyModel>().OrderBy(modelKey => modelKey.ID).Last();
    System.Diagnostics.Debug.WriteLine($"{whatIsTheKey.ID} : {whatIsTheKey.Humanized}");
}

Gap'ie key ordering (refetch the last record by indexed ID):

Note: "Gap'ie" is Trademark pending ;-)

var rand = new Random();
var config = RealmConfiguration.DefaultConfiguration;
config.SchemaVersion = 1;
using (var theRealm = Realm.GetInstance("StackOverflow.realm"))
{
    theRealm.Write(() =>
    {
        for (int i = 1; i < 1000; i++)
        {
            var lastID = theRealm.All<IdIntKeyModel>().OrderByDescending(modelKey => modelKey.ID).FirstOrDefault();
            var model = theRealm.CreateObject<IdIntKeyModel>();
            model.ID = lastID != null ? lastID.ID + rand.Next(10) : 1; // use lastID.ID++ for normal code flow, using rand.Next as a test to check ID indexing
            model.Humanized = model.ID.ToWords();
        }
    });
    var lastKey = theRealm.All<IdIntKeyModel>().OrderBy(modelKey => modelKey.ID).Last();
    System.Diagnostics.Debug.WriteLine($"{lastKey.ID} : {lastKey.Humanized}");
}

Note: Code updates based on added support for FirstOrDefault, tested w/ v0.78.1

Community
  • 1
  • 1
SushiHangover
  • 73,120
  • 10
  • 106
  • 165
0

"In Xamarin there isn't a where" is not correct - we support LINQ as you can see in the snippets on the home page.

However, you are correct that we don't (yet) have an auto-increment or anything for that role.

We will get something at some point, but due to synchronisation issues it will not be auto-increment, but rather something like auto-unique-id.

We just released the full Mobile Platform with sync (Xamarin is getting there). One of the big deals of the Realm Object Server is dealing with people who are editing offline data and then having highly reliable synchronisation to other Realms.

There is no way that simple auto-increment can be made to work with disconnected data creation (the first time I dealt with this was on a Mac back in 1996 but the laws of physics haven't changed, we just stopped using floppy disks).

Andy Dent
  • 17,578
  • 6
  • 88
  • 115
  • Is there any link/page/resource that states this limitation on Realm website? I tried searching on limitation page and FAQ but nothing. An honest approach would require not to hide this important limitation. – Daniele D. Oct 25 '16 at 11:14
  • Really sorry if you got the impression that we hide any limitations - that’s certainly not our intent. On the contrary, all our code is public, our outstanding issues and the stuff we work on is totally transparent on github. We try to be very transparent. By nature it’s hard to write all the things we don’t support - it’s a balance. That said, we add to the FAQ and Limitations anything we hear often. This is the first time we got this question, but never the less it would be good to get the workaround documented." – bmunk Oct 27 '16 at 23:35
0

where clause is actually supported by Realm. You only need to import linq. However, auto increment id is really a big deal.

I solved auto increment issue by creating my own id

using Realms;
using System;

namespace RealmDatabase
{
  public class RealmUserObject : RealmObject
  {
    [PrimaryKey]
    public int userID { get; set; }
    public string userLoginName { get; set; }
    public DateTimeOffset userCreated { get; set; }
    public bool userActive { get; set; }
  }
}

and then when adding account, i'm getting last user info from realm then get the last id from it ( which is int ) then + 1 before to insert new account.

public List<RealmUserObject> getAllUserAccountsFromDatabase()
{
    try
    {
        realm = Realm.GetInstance(config);
        return realm.All<RealmUserObject>().Last();
    }
    catch (Exception) { throw; }
}

i am calling whole account because it is useful for me in other scenario. but you can actually ask directly what you want like this way

return realm.All<RealmUserObject>().Last().userID;

note: ofcourse the issue with this is what if you don't have any record existing, then just insert it and make id initial to 1 and put else if account is greater than 0

jace
  • 1,634
  • 3
  • 14
  • 41