cor*_*lha 4 foreign-key-relationship servicestack ormlite-servicestack
我创建了以下示例来测试外键,到目前为止,它运行良好.我希望能够做的是使用我构建的这个框架来设置关系的属性,并在保存Parent时保存子对象并自动设置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;
}
}
Run Code Online (Sandbox Code Playgroud)
这些是我的POCO,其中BaseClass用于实现我的结果:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
创建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;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是用法:
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);
}
Run Code Online (Sandbox Code Playgroud)
输出如我所料:
约翰·多伊1
杰克史密斯2
彼得琼斯3
丹哈迪4
PN:12345679 1
PN:12345679 2
PN:12345679 3
PN:12345679 4
1:John Doe 12345679
2:杰克史密斯12345679
3:Peter Jones 12345679
4:Dan Hardy 12345679
我真正希望能做的是以下内容:
var john = new Person
{
Name = "John",
Surname = "Smith",
PhoneNumber = new PhoneNumber { Number = "123456789" }
};
conn.Save<Person>(john);
var number = john.PhoneNumber.Number
Run Code Online (Sandbox Code Playgroud)
这是可能吗?
默认情况下,OrmLite v3会在字符串字段中填充所有复杂类型属性,您需要显式设置所有引用.
在下一个主要的v4版本(2013年11月下旬的ETA)中,OrmLite 使用该属性添加了对外部引用的一些支持[Reference],这使您可以告诉OrmLite这些属性应该存储在外部表中而不是blobbed,例如:
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; }
}
Run Code Online (Sandbox Code Playgroud)
这将允许您调用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));
Run Code Online (Sandbox Code Playgroud)
要获得更细粒度的控制,您还可以选择要保存的参考,例如:
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);
Run Code Online (Sandbox Code Playgroud)
然后,您可以加载主行及其所有引用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));
Run Code Online (Sandbox Code Playgroud)