【问题标题】:Retrieve object with all child elements (and sub child elements)检索具有所有子元素(和子子元素)的对象
【发布时间】:2017-11-26 23:35:45
【问题描述】:

我想检索一个object,它本身有一些object 类型的属性。这些子对象再次包含一些object 作为属性。

如果我尝试从数据库中检索数据,我会得到第一级子级的结果,但后续级别的数据是null。在下面的示例中,Windownull。从其他属性中,我按预期返回数据。如果我查看数据库,这种关系似乎是正确的。只有读取数据有问题。

关系

汽车

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; }
}

窗口

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 包。

【问题讨论】:

    标签: c# sqlite xamarin sqlite-net sqlite-net-extensions


    【解决方案1】:

    您应该使用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);
    

    【讨论】:

    • 我将CascadeOperation 属性添加到CarDoorrecursive 也适用于 GetCarAsync()GetDoorAsync()Window 的结果仍然是 null。我必须以不同的方式存储它还是应该使用CascadeInsert
    • 好吧,我的错。我从文件系统中完全删除了数据库,现在它可以工作了。旧数据库还在……还有一个问题:CascadeRead 可以与CascadeInsert 结合使用吗?还是只能存在一个或另一个?什么时候使用?
    • 你可以同时使用:[OneToMany(CascadeOperations = CascadeOperation.CascadeRead | CascadeOperation.CascadeInsert)]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2020-03-16
    • 1970-01-01
    • 2020-02-21
    相关资源
    最近更新 更多