检索 object 与所有 child 元素(和子 child 元素)
Retrieve object with all child elements (and sub child elements)
我想检索一个 object
,它本身有一些 object
类型的属性。这些 child objects 再次包含一些 object
作为属性。
如果我尝试从数据库中检索数据,我会在第一层得到 children 的结果,但后续层的数据是 null
。在下面的例子中 Window
是 null
。从其他属性中,我按预期取回了数据。如果我查看数据库,关系似乎是正确的。只是读取数据有问题。
关系
汽车
public class Car
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Model { get; set; }
public string Color { get; set; }
[ForeignKey(typeof(Door))]
public int DoorId { get; set; }
[OneToOne]
public Door Door { get; set; }
}
门
public class Door
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Side { get; set; }
[ForeignKey(typeof(Window))]
public int WindowId { get; set; }
[OneToOne]
public Window Window { get; set; }
}
Window
public class Window
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public bool Automatic { get; set; }
}
例子
public MainPage()
{
InitializeComponent();
Window window = new Window();
window.Automatic = true;
Door door = new Door();
door.Side = "left";
door.Window = window;
Car car = new Car();
car.Color = "red";
car.Model = "MX5";
car.Door = door;
this.car = car;
}
protected override async void OnAppearing()
{
base.OnAppearing();
await App.Database.StoreCarAsync(this.car);
Car existingCar = await App.Database.GetCarAsync(this.car.Id);
System.Diagnostics.Debug.WriteLine("finished");
}
数据库
public class Database
{
private readonly SQLiteAsyncConnection database;
public Database(string databasePath)
{
this.database = new SQLiteAsyncConnection(databasePath);
this.database.CreateTableAsync<Car>().Wait();
this.database.CreateTableAsync<Door>().Wait();
this.database.CreateTableAsync<Window>().Wait();
}
public async Task<Car> GetCarAsync(int carId)
{
var queryResult = await this.database.Table<Car>().Where(c => c.Id == carId).CountAsync();
if (queryResult > 0)
{
return await this.database.GetWithChildrenAsync<Car>(carId);
}
else
{
return null;
}
}
public async Task<Door> GetDoorAsync(int doorId)
{
var queryResult = await this.database.Table<Door>().Where(d => d.Id == doorId).CountAsync();
if (queryResult > 0)
{
return await this.database.GetWithChildrenAsync<Door>(doorId);
}
else
{
return null;
}
}
public async Task<Window> GetWindowAsync(int windowId)
{
var queryResult = await this.database.Table<Window>().Where(w => w.Id == windowId).CountAsync();
if (queryResult > 0)
{
return await this.database.GetWithChildrenAsync<Window>(windowId);
}
else
{
return null;
}
}
public async Task StoreCarAsync(Car car)
{
await this.StoreDoorAsync(car.Door);
var foundItem = await this.GetCarAsync(car.Id);
if (foundItem != null)
{
await this.database.UpdateWithChildrenAsync(car);
}
else
{
await this.database.InsertWithChildrenAsync(car);
}
}
public async Task StoreDoorAsync(Door door)
{
await this.StoreWindowAsync(door.Window);
var foundItem = await this.GetDoorAsync(door.Id);
if (foundItem != null)
{
await this.database.UpdateWithChildrenAsync(door);
}
else
{
await this.database.InsertWithChildrenAsync(door);
}
}
public async Task<int> StoreWindowAsync(Window window)
{
var foundItem = await this.GetWindowAsync(window.Id);
if (foundItem != null)
{
return await this.database.UpdateAsync(window);
}
else
{
return await this.database.InsertAsync(window);
}
}
}
这是不可能的还是我做错了什么?
PS:我正在使用最新的 SQLiteNetExtensions.Async v2.0.0-alpha2
NuGet 包。
您应该使用 cascaded read 来阅读完整的关系层次结构。首先标记你的实体关系以允许级联读取,例如:
public class Car
{
//snip
[OneToOne(CascadeOperations = CascadeOperation.CascadeRead)]
public Door Door { get; set; }
}
然后当你从数据库读取时,将recursive
参数设置为true。例如:
return await this.database.GetWithChildrenAsync<Door>(doorId, recursive: true);
我想检索一个 object
,它本身有一些 object
类型的属性。这些 child objects 再次包含一些 object
作为属性。
如果我尝试从数据库中检索数据,我会在第一层得到 children 的结果,但后续层的数据是 null
。在下面的例子中 Window
是 null
。从其他属性中,我按预期取回了数据。如果我查看数据库,关系似乎是正确的。只是读取数据有问题。
关系
汽车
public class Car
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Model { get; set; }
public string Color { get; set; }
[ForeignKey(typeof(Door))]
public int DoorId { get; set; }
[OneToOne]
public Door Door { get; set; }
}
门
public class Door
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Side { get; set; }
[ForeignKey(typeof(Window))]
public int WindowId { get; set; }
[OneToOne]
public Window Window { get; set; }
}
Window
public class Window
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public bool Automatic { get; set; }
}
例子
public MainPage()
{
InitializeComponent();
Window window = new Window();
window.Automatic = true;
Door door = new Door();
door.Side = "left";
door.Window = window;
Car car = new Car();
car.Color = "red";
car.Model = "MX5";
car.Door = door;
this.car = car;
}
protected override async void OnAppearing()
{
base.OnAppearing();
await App.Database.StoreCarAsync(this.car);
Car existingCar = await App.Database.GetCarAsync(this.car.Id);
System.Diagnostics.Debug.WriteLine("finished");
}
数据库
public class Database
{
private readonly SQLiteAsyncConnection database;
public Database(string databasePath)
{
this.database = new SQLiteAsyncConnection(databasePath);
this.database.CreateTableAsync<Car>().Wait();
this.database.CreateTableAsync<Door>().Wait();
this.database.CreateTableAsync<Window>().Wait();
}
public async Task<Car> GetCarAsync(int carId)
{
var queryResult = await this.database.Table<Car>().Where(c => c.Id == carId).CountAsync();
if (queryResult > 0)
{
return await this.database.GetWithChildrenAsync<Car>(carId);
}
else
{
return null;
}
}
public async Task<Door> GetDoorAsync(int doorId)
{
var queryResult = await this.database.Table<Door>().Where(d => d.Id == doorId).CountAsync();
if (queryResult > 0)
{
return await this.database.GetWithChildrenAsync<Door>(doorId);
}
else
{
return null;
}
}
public async Task<Window> GetWindowAsync(int windowId)
{
var queryResult = await this.database.Table<Window>().Where(w => w.Id == windowId).CountAsync();
if (queryResult > 0)
{
return await this.database.GetWithChildrenAsync<Window>(windowId);
}
else
{
return null;
}
}
public async Task StoreCarAsync(Car car)
{
await this.StoreDoorAsync(car.Door);
var foundItem = await this.GetCarAsync(car.Id);
if (foundItem != null)
{
await this.database.UpdateWithChildrenAsync(car);
}
else
{
await this.database.InsertWithChildrenAsync(car);
}
}
public async Task StoreDoorAsync(Door door)
{
await this.StoreWindowAsync(door.Window);
var foundItem = await this.GetDoorAsync(door.Id);
if (foundItem != null)
{
await this.database.UpdateWithChildrenAsync(door);
}
else
{
await this.database.InsertWithChildrenAsync(door);
}
}
public async Task<int> StoreWindowAsync(Window window)
{
var foundItem = await this.GetWindowAsync(window.Id);
if (foundItem != null)
{
return await this.database.UpdateAsync(window);
}
else
{
return await this.database.InsertAsync(window);
}
}
}
这是不可能的还是我做错了什么?
PS:我正在使用最新的 SQLiteNetExtensions.Async v2.0.0-alpha2
NuGet 包。
您应该使用 cascaded read 来阅读完整的关系层次结构。首先标记你的实体关系以允许级联读取,例如:
public class Car
{
//snip
[OneToOne(CascadeOperations = CascadeOperation.CascadeRead)]
public Door Door { get; set; }
}
然后当你从数据库读取时,将recursive
参数设置为true。例如:
return await this.database.GetWithChildrenAsync<Door>(doorId, recursive: true);