【问题标题】:Xamarin forms SQLite relationXamarin 形成 SQLite 关系
【发布时间】:2018-11-20 22:59:31
【问题描述】:

我将在 Xamarin 表单中创建一个应用程序,并从 SQLite 开始。我需要为应用程序中的每个主要项目提供唯一的列表项目。

例如,我有一个包含项目的列表。当我在列表中选择一个项目时,会弹出一个新页面并显示该项目的项目。

所以从我的角度来看,我需要两个具有关系的 SQLite 表。

这是包含所有配置文件的主表

[Table("Profiles")]
public class ProfileItems
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string ProfileName { get; set; }
    public string ProfileRace { get; set; }
    public string iconn = "icon.png";
    public string ProfileIcon { get; set; }
    public DateTime BDay { get; set; }

    [OneToMany(CascadeOperations = CascadeOperation.All)]
    public List<LoggItems> Loggs { get; set; }

}

这是每个配置文件的日志表,每个配置文件应该是唯一的

[Table("Loggs")]
public class LoggItems
{
    [PrimaryKey, AutoIncrement]

    public int Id { get; set; }
    public string Title { get; set; }
    public string Text { get; set; }

    [ForeignKey(typeof(ProfileItems))]
    public int ProfileId { get; set; }
}

添加这样的项目

public class ProfileDatabase
{

    readonly SQLiteAsyncConnection database;

    public ProfileDatabase(string dbPath)
    {
        database = new SQLiteAsyncConnection(dbPath);
        database.CreateTableAsync<ProfileItems>().Wait();
        database.CreateTableAsync<LoggItems>().Wait();
    }
    

    //Profile
    public Task<List<ProfileItems>> GetProfileAsync()
    {
        return database.Table<ProfileItems>().ToListAsync();
    }

    public Task<ProfileItems> GetProfileAsync(int id)
    {
        return database.Table<ProfileItems>().Where(i => i.Id == id).FirstOrDefaultAsync();
    }

    public Task<int> SaveProfileAsync(ProfileItems profileItems)
    {
        if (profileItems.Id != 0)
        {
            return database.UpdateAsync(profileItems);
        }
        else
        {
            return database.InsertAsync(profileItems);
        }
    }

    public  Task<int> DeleteProfileAsync(ProfileItems profileItems)
    {
        return database.DeleteAsync(profileItems);
    }


    //Logg
    public Task<List<LoggItems>> GetLoggAsync()
    {
        return database.Table<LoggItems>().ToListAsync();
    }

    public Task<LoggItems> GetLoggAsync(int id)
    {
        return database.Table<LoggItems>().Where(i => i.Id == id).FirstOrDefaultAsync();
    }

    public Task<int> SaveLoggAsync(LoggItems loggItems)
    {
        if (loggItems.Id != 0)
        {
            return database.UpdateAsync(loggItems);
        }
        else
        {
            return database.InsertAsync(loggItems);
        }
    }

    public Task<int> DeleteLoggAsync(LoggItems loggItems)
    {
        return database.DeleteAsync(loggItems);
    }
}

Logg 和配置文件列表/表格都可以工作,但它们之间没有任何关系,因此日志在所有配置文件中显示相同。

我应该怎么做?

【问题讨论】:

    标签: c# sqlite xamarin xamarin.forms


    【解决方案1】:

    我认为您必须添加“virtual”关键字才能启用延迟加载。

    [OneToMany(CascadeOperations = CascadeOperation.All)]
    public virtual List<LoggItems> Loggs { get; set; }
    

    还有“[InverseProperty]”来指定它们相关的导航属性。

    public class LoggItems
    {
         *
         [ForeignKey(typeof(ProfileItems))]
         [InverseProperty("Loggs")]
         public int ProfileId { get; set; }
         *
    }
    

    【讨论】:

    • 感谢您的回复。有些事情我真的不明白。首先,如何添加 [InverserProperty],它是内置在 SQLite 中还是 nuget?第二。我真的不知道我是否正确添加了这些项目。我不应该将日志添加到 Loggs 列表中吗? (public virtual List Loggs { get; set; }),现在日志只是作为一个新的 Logg 项添加。那会奏效吗?第三。如何调用每个配置文件项的子项。现在我只绑定到 LoggItem 类中的项目,如果我理解正确的话,它只会生成一个新的父级。
    • 1.- [InverseProperty] 它是sqlite的数据注释,用于表示导航属性。这里有一些帮助Link 2.- 您拥有的项目是正确的,我建议将列 id 称为表的名称,例如 ProfileItemsIdLoggItemsId 3.- 当您将表格与您可以调用的属性相关联,如下所示:var list = database.ProfileItems.ToList(); 在该列表中,您将拥有您在课堂上标记的所有属性及其子项。
    • 您有可以与我们分享的存储库吗?
    • 我无法编译,你必须将repo添加到.sln所在的主文件夹
    • 我找到了这个 GetAllWithChildrenAsync(),试图弄清楚它是如何工作的。也许你以前用过?
    【解决方案2】:

    如何使用 Linq 并加入关系。
    1.-首先你必须添加命名空间:

    using System.Linq;
    

    2.- 将 ProfileItems 类中的属性更改为 IEnumerable

    [OneToMany(CascadeOperations = CascadeOperation.All)]
    public virtual IEnumerable<LoggItems> Loggs { get; set; }
    

    3.- 这是将日志与配置文件项连接的方法。

    var profiles = await GetProfileAsync();
    var loggs = await GetLoggAsync();
    var query = from p in profiles
        join l in loggs on p.Id equals l.ProfileId into list
        select new ProfileItems
        {
            Id = p.Id,
            ProfileIcon = p.ProfileIcon,
            ProfileName = p.ProfileName,
            ProfileRace = p.ProfileRace,
            BDay = p.BDay,
            Loggs = list
        };
    

    【讨论】:

    • 立即尝试。我已经添加了整个解决方案github.com/merlieon/Doggalogg 我尝试了您的 GetProfileInclude() 但收到错误,我无法在异步方法中使用 Include。
    • 在 InverseProperty 上也出现错误。严重性代码 描述 项目文件行抑制状态错误 CS0246 找不到类型或命名空间名称“InverseProperty”(是否缺少 using 指令或程序集引用?) D​​oggaLogg.Android、DoggaLogg.iOS、DoggaLogg.UWP C:\Users \mawil3\source\repos\DoggaLogg\DoggaLogg\DoggaLogg\Model\LoggItems.cs 27 活动
    • 我无法编译您的解决方案,我不知道,但它缺少一些东西。我们可以尝试使用 linq with joins 并获取你需要的所有属性,去掉 inverse 属性我会写一个例子。
    • 对不起,我应该在哪里使用该方法?
    • 我在你的repo上发表了,看看吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多