Xamarin.Android:SQLite-Net 扩展多对多 - 没有这样的 table,NULL 集合

Xamarin.Android: SQLite-Net Extensions many-to-many - no such table, NULL collection

我在 Visual Studio 2015 年的 Xamarin.Android 项目中安装了 SQLite-Net Extensions 包,我正在尝试在 PersonEvent实体。我关注了 the official documentation of the library,但我无法让它正常工作。

类 我创建了:

Person.cs:

[Table("People")]
public class Person
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    public string Name { get; set; }

    public string LastName { get; set; }

    public string PhoneNumber { get; set; }

    public string Email { get; set; }

    [ManyToMany(typeof(PersonEvent), CascadeOperations = CascadeOperation.All)]
    public List<Event> Events { get; set; }
}

Event.cs:

[Table("Events")]
public class Event
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    public string Name { get; set; }
    public DateTime Date { get; set; }
    public string Place { get; set; }

    [ManyToMany(typeof(PersonEvent), CascadeOperations = CascadeOperation.All)]
    public List<Person> Participants { get; set; }
}

个人Event.cs:

public class PersonEvent
{
    [ForeignKey(typeof(Person))]
    public int PersonId { get; set; }

    [ForeignKey(typeof(Event))]
    public int EventId { get; set; }
}

为了测试它,我删除了数据库文件以确保在设备上创建了一个干净的文件,然后尝试创建一个 Person、一个 Event,将两者都插入到先DB,然后将Event分配给Person,然后使用UpdateWithChildren方法再次保存:

var dbFile = new File(Constants.DbFilePath);
dbFile.Delete();

var db = new SQLiteConnection(new SQLitePlatformAndroid(), Constants.DbFilePath);
db.CreateTable<Person>();
db.CreateTable<Event>();
db.CreateTable<PersonEvent>();

var event1 = new Event
{
    Name = "Volleyball",
    Date = new DateTime(2017, 06, 18),
    Place = "Sports hall"
};

var person1 = new Person
{
    Name = "A",
    LastName = "B",
    PhoneNumber = "123456789"
};


db.Insert(person1);
db.Insert(event1);
person1.Events = new List<Event> { event1 };
db.UpdateWithChildren(person1);

首先,我需要添加 CreateTable<PersonEvent>() 行,因为如果它不存在,我会得到异常:SQLite.Net.SQLiteException: no such table: PersonEvent,但我认为我不必创建这个中间table 手动。 SQLite-Net Extensions 不应该以某种方式自动创建它吗?

添加此行后,event1person1 的前两个插入工作正常(插入后两个实体都分配了 ID)。 person1 上的 Events 集合甚至创建了 Event,它也设置了 Id:

但是,"opposite entity",在本例中 event1 有其 Participants 集合(列表 PersonNULL:

我尝试了所有方法,但没有任何效果。据我了解阅读 SQLite-Net Extensions 文档,它应该自动解决。我什至在集合中添加了这个 CascadeOperations = CascadeOperation.All,但如您所见,它没有帮助。我还是做错了什么?

The Events collection on person1 has even the Event created, which also has Id set

您的 person1 对象具有您创建的事件列表。该集合包含一个 link 到您创建的 event1 对象。当您插入或更新数据库时,此事件集合未更新。当您将 Event 对象插入数据库时​​,您会发现它设置了 Id,因为列表包含相同的对象。

SQLite-NET Extensions 不是 [自动] 延迟加载解决方案(如 Entity Framework)。它只有在被告知时才会获取对象。使用 Get 方法从数据库中获取对象与 SQLite 已经做的没有任何不同。这是因为 SQLite-NET Extensions 不会改变该方法。但是它确实提供了像 GetWithChildren and FindWithChildren 这样的新方法。如果你想获得一个对象的子对象,你需要 SQLite-NET Extensions 提供的方法。

提供的示例也使用了这些方法:

// Get the object and the relationships
var storedValuation = db.GetWithChildren<Valuation>(valuation.Id);
if (euro.Symbol.Equals(storedValuation.Stock.Symbol)) {
    Debug.WriteLine("Object and relationships loaded correctly!");
}

您也不希望对象从 Person-Event-Person-Event 等递归加载。因为这永远不会结束。如果您从一个人开始,并希望让所有人都与某个事件相关联,那么您会希望在另一个电话中获得这些人。

var person = db.GetWithChildren(1);
foreach(var event in person.Events)
{
    // lazy load ourselves
    var allParticipants = db.GetWithChildren(event.Id).Participants;
}

希望对您有所帮助

如果有人想查看有关使用 SQLite-Net Extensions 库创建多对多关系的更多详细信息,还包含@Shawn Kendrot 在此处提供的提示和解决方案,我已经收集了所有内容并且 wrote a post on my blog .

希望对您有所帮助:)