4

外部キーをテストするために次の例を作成しましたが、この時点まではうまく機能しています。私ができるようにしたいのは、私が構築したこのフレームワークを使用して、関係のプロパティを設定し、親が保存されたときに子オブジェクトを保存し、PrimaryKey と Foreign Key を自動的に設定することです。DataManager クラスは Connection を公開します

 public class DataManager
{

    DataManager()
    {
        OrmLiteConfig.DialectProvider = SqliteDialect.Provider;
        ConnectionString = SqliteFileDb;
        updateTables();
    }

    private void updateTables()
    {
        using (var dbConn = OpenDbConnection())
        {
            dbConn.DropAndCreateTable<Person>();
            dbConn.DropAndCreateTable<PhoneNumber>();
        }
    }
    public static string SqliteFileDb = "~/App_Data/db.sqlite".MapAbsolutePath();
    private static DataManager manager;
    public static DataManager Manager {

        get
        {
            if (manager == null)
                manager = new DataManager();
            return manager;
        }
    }
    public IDbConnection InMemoryDbConnection { get; set; }
    public IDbConnection OpenDbConnection(string connString = null)
    {
        connString = ConnectionString;
        return connString.OpenDbConnection();
    }
    protected virtual string ConnectionString { get; set; }
    protected virtual string GetFileConnectionString()
    {
        var connectionString = SqliteFileDb;
        return connectionString;
    }
}

これらは、結果を達成するために使用される BaseClass を使用した私の POCO です。

    public class Person : LiteBase
{
    [AutoIncrement]
    [PrimaryKey]
    public int Id { get; set; }

    public string Name { get; set; }
    public string Surname { get; set; }
    private List<PhoneNumber> numbers;
    public List<PhoneNumber> PhoneNumbers {
        get
        {
            if (numbers == null)
                numbers = GetList<PhoneNumber>(p => p.Person == Id);
            return numbers;
        }
    }

}

public class PhoneNumber
{
    public string Number { get; set; }
    public string Description { get; set; }

    [AutoIncrement]
    [PrimaryKey]
    public int Id { get; set; }

    [References(typeof (Person))]
    public int Person { get; set; }

    public void AddPerson(Person person)
    {
        Person = person.Id;
    }
}

public class LiteBase:INotifyPropertyChanged
{
    public List<T> GetList<T>(Expression< Func<T,bool>> thefunction) where T : new()
    {
        var objects = new List<T>();
        using (var conn = Data.DataManager.Manager.OpenDbConnection())
        {
            objects = conn.Where<T>(thefunction);
        }
        return objects;
    }

    public T GetItem<T>(Expression<Func<T, bool>> thefunction) where T : new()
    {
        T obj = new T();
        using (var conn = Data.DataManager.Manager.OpenDbConnection())
        {
            obj = conn.Where<T>(thefunction).FirstOrDefault<T>();
        }
        return obj;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) 
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Person オブジェクトと PhoneNumber オブジェクトを作成する単純なクラス

 public class PersonManager
    {

        public void CreatePerson(string name, string surname, string number)
        {
            using (var conn = DataManager.Manager.OpenDbConnection())
            {
                var pnum = new PhoneNumber { Number = number };
                var person = new Person
                    {
                        Name=name,
                        Surname = surname,

                    };
                conn.Save<Person>(person);
                var id = conn.GetLastInsertId();
                person.Id = (int)id;
                pnum.AddPerson(person);
                conn.Save<PhoneNumber>(pnum);

            }
        }

        public List<Person> GetPeople()
        {
            List<Person> people;
            using (var conn = DataManager.Manager.OpenDbConnection())
            {
                people = conn.Select<Person>();
            }
            return people;
        }

        public List<PhoneNumber> GetNumbers()
        {
            List<PhoneNumber> numbers;
            using (var conn = DataManager.Manager.OpenDbConnection())
            {
                numbers = conn.Select<PhoneNumber>();
            }
            return numbers;
        }
    }

そして、ここに使用法があります:

var manager = new PersonManager();
        manager.CreatePerson("John", "Doe", "12345679");
        manager.CreatePerson("Jack", "Smith", "12345679");
        manager.CreatePerson("Peter", "Jones", "12345679");
        manager.CreatePerson("Dan", "Hardy", "12345679");
        var people = manager.GetPeople();
        var numbers = manager.GetNumbers();
        for (int i = 0; i < people.Count; i++)
        {
            Console.WriteLine("{0} {1} {2}",
                people[i].Name,people[i].Surname,people[i].Id);
        }
        for (int n = 0; n < numbers.Count; n++)
        {
            Console.WriteLine("PN: {0} {1}",
                numbers[n].Number,numbers[n].Person);
        }
        for (int p = 0; p < people.Count; p++)
        {
            var person = people[p];
            Console.WriteLine("{0}: {1} {2} {3}",
                person.Id,person.Name,person.Surname,person.GetItem<PhoneNumber>(x=>x.Person==person.Id).Number);
        }

出力は私が期待したとおりです:

ジョン・ドウ 1

ジャック・スミス 2

ピーター・ジョーンズ 3

ダン・ハーディ 4

PN: 12345679 1

PN: 12345679 2

PN: 12345679 3

PN: 12345679 4

1: ジョン・ドウ 12345679

2: ジャック・スミス 12345679

3: ピーター・ジョーンズ 12345679

4: ダン・ハーディ 12345679

私が本当にできるようにしたいのは、次のことです。

var john = new Person
                {
                    Name = "John",
                    Surname = "Smith",
                    PhoneNumber = new PhoneNumber { Number = "123456789" }
                };
                conn.Save<Person>(john);
                var number = john.PhoneNumber.Number

これはまったく可能ですか?

4

1 に答える 1

6

デフォルトでは、OrmLite v3 はすべての複合型プロパティを文字列フィールドにブロブし、すべての参照を明示的に設定する必要があります。

次のメジャー v4 リリース (ETA 2013 年 11 月下旬) では、OrmLiteは属性を使用した外部参照のサポートを追加[Reference]します。これにより、OrmLite にこれらのプロパティを外部テーブルに保存し、ブロブしないように指示できます。

public class Customer
{
    [AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }

    [Reference]
    public CustomerAddress PrimaryAddress { get; set; }

    [Reference]
    public List<Order> Orders { get; set; }
}

db.SaveReferences()これにより、参照プロパティを保存するために呼び出すことができます。

var customer = new Customer
{
    Name = "Customer 1",
    PrimaryAddress = new CustomerAddress {
        AddressLine1 = "1 Humpty Street",
        City = "Humpty Doo",
        State = "Northern Territory",
        Country = "Australia"
    },
    Orders = new[] { 
        new Order { LineItem = "Line 1", Qty = 1, Cost = 1.99m },
        new Order { LineItem = "Line 2", Qty = 2, Cost = 2.99m },
    }.ToList(),
};

Assert.That(customer.Id, Is.EqualTo(0)); //Id is not saved yet

//Inserts customer, populates auto-incrementing customer.Id
//Specify `references:true` to populate the ForeignKey ids and 
//save the related rows as well, e.g:
db.Save(customer, references:true); 

Assert.That(customer.Id, Is.GreaterThan(0)); 
Assert.That(customer.PrimaryAddress.CustomerId, Is.EqualTo(customer.Id));
Assert.That(customer.Orders.All(x => x.CustomerId == customer.Id));

参照を手動で保存する

より細かく制御するために、保存する参照を選択することもできます。

db.Save(customer);  //Doesn't save related rows

//1:1 PrimaryAddress Reference not saved yet
Assert.That(customer.PrimaryAddress.CustomerId, Is.EqualTo(0));

//1:1 PrimaryAddress Reference saved and ForeignKey id populated
db.SaveReferences(customer, customer.PrimaryAddress);

//1:Many Orders References saved and ForeignKey ids populated
db.SaveReferences(customer, customer.Orders);

エンティティに関連するすべての行をロードする

次に、マスター行とそのすべての参照を次のようにロードできますdb.LoadSingleById

var dbCustomer = db.LoadSingleById<Customer>(customer.Id);

dbCustomer.PrintDump();

Assert.That(dbCustomer.PrimaryAddress, Is.Not.Null);
Assert.That(dbCustomer.Orders.Count, Is.EqualTo(2));
于 2013-11-07T08:20:45.087 に答える