2015-10-21 28 views
1

上下文: 我們使用SQLite-Net Extensions進行本地數據緩存,使用Xamarin。我們計劃部署到iOS,Android和Windows Phone。我們在整個系統中都使用了現有的數據結構(都實現了一個通用接口),我們希望以這種方式進行存儲。如何將外鍵映射到SQLite-Net Extensions中的對象字段?

問題 作爲代碼示例中所示,[ManyToOne]屬性用於表示的關係字段。這不起作用。如BitBucket Developer Page所述,[ForeignKey]屬性可用於指定外鍵關係。這貌似只支持int。我們是否可以輕鬆調整我們的結構以支持這些關係,而無需重複Id字段的屬性。例如以下是不可取的。

[ForeignKey(typeof(Address))] 
    public int AddressId { set; get; } 

    [ManyToOne] 
    public Address Address 
    { 
     set { address = value; } 
     get { return address; } 
    } 

代碼示例

using SQLite.Net.Attributes; 
using SQLiteNetExtensions.Attributes; 

namespace Data 
{ 
    [Table("Client")] 
    public class Client : IData 
    { 
     private int id = -1; 
     private Address address = null; 

     public Client() { } 

     public Client(int id) 
     { 
      this.id = id; 
     } 

     [PrimaryKey, AutoIncrement, Column("_id")] 
     public int Id 
     { 
      set { id = value; } 
      get { return id; } 
     } 

     [ManyToOne] 
     public Address Address 
     { 
      set { address = value; } 
      get { return address; } 
     } 
    } 

    [Table("Address")] 
    public class Address : IIdentifiable 
    { 
     private int id = -1; 
     private string someFields = ""; 

     public Address() { } 

     public Address(int id) 
     { 
      this.id = id; 
     } 

     [PrimaryKey, AutoIncrement, Column("_id")] 
     public int Id 
     { 
      set { id = value; } 
      get { return id; } 
     } 

     public string SomeFields 
     { 
      set { someFields = value; } 
      get { return someFields; } 
     } 
    } 
} 

回答

1
SQLite的

-Net的擴展結束的SQLite-Net的薄層,並且它使用SQLite數據庫爲存儲。關係數據庫使用外鍵存儲關係,而sqlite在這方面沒有什麼不同。因此,SQLite-Net和SQLite-Net Extensions也使用外鍵機制來聲明關係。

作爲一種替代方法,您可以使用中間表來存儲關係,與ManyToMany關係的工作方式相同,但將其中一個端點限制爲一個。通過這種方式,您可以使用ManyToMany關係和中間表來模擬OneToManyManyToOne甚至OneToOne的關係。例如:

[Table("Client")] 
public class Client { 

    [PrimaryKey, AutoIncrement, Column("_id")] 
    public int Id { get; set; } 

    [Ignore] // This property shouldn't be persisted 
    public Address Address { get; set; } 

    // This relationship is in fact a ManyToOne relationship, 
    // but we model it as a ManyToMany to avoid adding foreign key to this entity 
    [ManyToMany(typeof(AddressesClients))] 
    public Address[] Addresses { 
     get { return Address != null ? new []{ Address } : Address; } 
     set { Address = value.FirstOrDefault(); } 
    } 
} 

[Table("Address")] 
public class Address 
{ 
    [PrimaryKey, AutoIncrement, Column("_id")] 
    public int Id { get; set; } 

    public string SomeFields { get; set; } 

    [ManyToMany(typeof(AddressesClients), ReadOnly = true)] 
    public List<Client> Clients { get; set; } 
} 

// Intermediate table that defines the relationship between Address and Client 
class AddressesClients { 
    [PrimaryKey, AutoIncrement] 
    public int Id { get; set; } 

    [ForeignKey(typeof(Client))] 
    public int ClientId { get; set; } 

    [ForeignKey(typeof(Address))] 
    public int AddressId { get; set; } 
} 

當然,這會有一些性能損失。

至於PrimaryKey,你可以使用任何支持的類型,你有,如果你使用Guid作爲主鍵,外鍵使用完全相同的類型相反ForeignKey,即到類必須也是Guid。在演示項目中,我們已經使用了int(最高性能),string甚至UUID

+0

雖然這不是我們選擇的解決方案,但它是相似的。在我們的例子中,我們分叉了sqlite-net-extensions存儲庫並對其進行了修改。我們添加了一個新的自定義屬性來表示一個外鍵。然後,我們修改了內部讀/寫操作,以便每次檢測到該屬性時,都會寫入自定義關係表,存儲:源表,字段,對象標識和目標對象標識。 – TomTom

相關問題