c# – 领域:自动递增主键

我正在通过实施一个简单的财务簿记工具来尝试Realm.我正在使用类似于以下内容的模式(从基于sql的项目继承)

c# – 领域:自动递增主键

最初,我使用类型为long的PrimaryKey为所有这些表设置类.然后我了解到,至少截至2015年,领域doesn’t support auto-increment.在我自己的测试中,它似乎是真的,因为我得到一个例外,说0是一个重复的主键.

看一下getting started guide上的例子,我试图重新评估我是否真的需要特定的Id字段.在大多数情况下,除了在数据库中使用主键的潜在速度优势之外,我似乎并不特别做.但是,当我设置关系时,我认为Realm在幕后做这件事似乎是合理的.但有一个例外.

// TransactionLink.cs
using Realms;

namespace Finance.Models {
    public class TransactionLink : RealmObject {
        public Transaction Lhs { get; set; }
        public Transaction Rhs { get; set; }
    }
}

// Transaction.cs
using Realms;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Finance.Models {
    public class Transaction : RealmObject {
        [PrimaryKey]
        public long Id { get; set; }

        // ...

        [Ignored]
        public IQueryable<Transaction> LinkedTransactions {
            get {
                var lhs = Realm.All<TransactionLink>().Where(tl => tl.Lhs.Id == Id).Select(tl => tl.Rhs);
                var rhs = Realm.All<TransactionLink>().Where(tl => tl.Rhs.Id == Id).Select(tl => tl.Lhs);
                return lhs.Union(rhs);
            }
        }
    }
}

起初我认为可能有交易有一个字段IList< Transaction>但是我不喜欢将一个条目添加到它们中的删除的好处.必须维护单独的数据副本对我没有吸引力.我考虑过而不是使用Equals函数比较Id,因为我注意到RealmObject重载它(类似于tl => tl.Rhs.Equals(this)),但我不确定它将如何处理查询(也许我应该在发布这个问题之后尝试一下……但是我可以通过一些方法来测试它

好吧,在这一点上(我可能是错的)似乎我最好实现一些自动递增的东西.因此,在afore-mentioned stack overflow post中的示例之后,我提出了一些建议.

// IPrimaryKeyId.cs
namespace Finance.Context {
    public interface IPrimaryKeyId {
        long Id { get; set; }
    }
}

// Database.cs
using Finance.Models;
using Realms;
using System.Linq;
using System.Windows;
using static Finance.Context.Handle;

namespace Finance.Context {
    public class Database {
        //-------------------------------------------------------------------------------------------------------------+
        // Non-Static Interface: Provide access to all the tables in the database                                      |
        //-------------------------------------------------------------------------------------------------------------+
        private Realm Db { get; set; }
        public IQueryable<Bank>                  Banks                  { get { return Db.All<Bank>(); } }
        public IQueryable<Models.Transaction>    Transactions           { get { return Db.All<Models.Transaction>(); } }
        public IQueryable<TransactionLink>       TransactionLinks       { get { return Db.All<TransactionLink>(); } }
        // ...

        public void SetupExample() {
            AutoIncrement(new Bank { Name = "Cash" });
            var first = Banks.First();
            MessageBox.Show(first.Id.ToString() + ": " + first.Name);
        }

        public void AutoIncrement<T>(T obj) where T : RealmObject, IPrimaryKeyId {
            AutoIncrement(Db, obj);
        }

        public static void AutoIncrement<T>(Realm db, T obj) where T : RealmObject, IPrimaryKeyId {
            db.Write(() => {
                long id = db.All<T>().Max(el => el.Id);
                obj.Id = id + 1;
                db.Add(obj);
            });
        }
    }
}

afore-mentioned guide说领域不喜欢这些类中的继承,但它似乎可以通过这个简单的界面运行.问题是在调用Max()的行上会抛出NotSupportedException.所以现在我有一些潜在的问题要解决,其中任何一个都会让我前进.

> Max()的替代方法,用于确定最大Id
>验证在Linq查询中使用Equals(this)和放弃Ids的效果
>我没有考虑的另一种选择

这对我来说已经习以为常了,所以我想尽可能地做“事情方式”.关于如何更好地适应这种风格的任何其他评论都是受欢迎的.

对@Cristo的回应

调用异常的行是long id = db.All< T>().Max(el => el.Id);正如您在上面的代码片段中看到的那样.确切的文本是System.NotSupportedException:’不支持’Max’方法’.堆栈跟踪是

[External Code] 
Finance.exe!Finance.Context.Database.AutoIncrement.AnonymousMethod__0() Line 48 C#
[External Code] 
Finance.exe!Finance.Context.Database.AutoIncrement<Finance.Context.Handle>(Realms.Realm db, Finance.Context.Handle obj) Line 47 C#
Finance.exe!Finance.Context.Database.Create(string file) Line 74    C#
Finance.exe!Finance.MainWindow.Button_Click(object sender, System.Windows.RoutedEventArgs e) Line 14    C#
[External Code] 

其中第47行对应于db.Write(而48对应于调用Max的行

解决方法:

The problem is that on the line that calls Max() it throws a NotSupportedException

假设你有一个int | long | …类型作为主键,你可以在瞬态查询上使用Last()来获取最后一个| max id值并手动将其递增一个(因为Realm查询是延迟加载的,只有最后一个对象被实例化以确定主键的当前值.

例:

public class ItemModel : RealmObject
{
    public ItemModel() { }

    public ItemModel(int ID)
    {
        this.ID = ID;
    }

    [PrimaryKey]
    public int ID { get; set; }

    public static ItemModel Create()
    {
        ItemModel NewItemModel()
        {
            var q = Realm.GetInstance(Consts.realmDBName).All<ItemModel>();
            return new ItemModel(q.Any() ? q.Last().ID + 1 : 0);
        }

        if (Realm.GetInstance(Consts.realmDBName).IsInTransaction)
        {
            return NewItemModel();
        }
        // Use a pseudo transaction to ensure multi-process safety on obtaining the last record 
        using (var trans = Realm.GetInstance(Consts.realmDBName).BeginWrite())
        {
            return NewItemModel();
        }
    }

}

用法:

var aRealmObject = instance.Add(ItemModel.Create(), false);
上一篇:java – Android领域 – 从服务访问领域对象


下一篇:java – 如何在领域浏览器中查看我的Realm文件?