2016-10-12 38 views
1

我并不是说这是明智的,但有时您会继承一些只需要工作的东西。在这种情况下,它是PK的Guids ...如何将GUID用作System.Data.Sqlite的主键

开箱即用,您会收到关于System.Guid与byte [](或String,如果您使用BinaryGUID = False)不起作用的错误。

回答

1

要解决这个问题,您需要截取byte []数组(或字符串),而不是返回Guid类型。这可以通过System.Data.Sqlite提供程序来实现。

首先

using System.Data.SQLite; 

然后,把这个在你的代码,第一DB上下文的构造:

var con = (SQLiteConnection)base.Database.Connection; 
var bind = System.Data.SQLite.SQLiteTypeCallbacks.Create(
       null, 
       new SQLiteReadValueCallback(GuidInterceptor), null, null); 
con.SetTypeCallbacks("uniqueidentifier", bind); 
con.SetTypeCallbacks("", bind); //Sometimes, the system just doesn't know 
con.Flags |= SQLiteConnectionFlags.UseConnectionReadValueCallbacks; 

然后这是一个神奇的功能:

private void GuidInterceptor(SQLiteConvert convert, SQLiteDataReader reader, SQLiteConnectionFlags flags, SQLiteReadEventArgs args, string typename, int index, object userdata, out bool complete) 
    { 
     complete = false; 
     if (typename == "uniqueidentifier") 
     { 
      var e = (SQLiteReadValueEventArgs)args; 

      var o = reader.GetGuid(index); 
      e.Value.Value = o; 
      e.Value.GuidValue = o; 
      complete = true; 
     } 
     else 
     { 
      var o = reader.GetValue(index); 
      if (o is byte[]) 
      { 
       var b = (byte[])o; 
       if (b.Length == 16) 
       { 
        var e = (SQLiteReadValueEventArgs)args; 
        var g = new Guid(b); 
        e.Value.Value = g; 
        e.Value.GuidValue = g; 
        complete = true; 
       } 
      } 
      else if (o is string) 
      { 
       var s = (string)o; 
       if (s.Length == 36) 
       { 
        var e = (SQLiteReadValueEventArgs)args; 
        var goGuid = (e.MethodName == "GetGuid"); 
        if (!goGuid) 
         goGuid = (s[8] == '-' && s[13] == '-' && s[18] == '-' && s[23] == '-'); 

        Guid g; 
        if (goGuid && Guid.TryParse(s, out g)) 
        { 
         e.Value.Value = g; 
         e.Value.GuidValue = g; 
         complete = true; 
        } 
        else 
        { 

        } 

       } 
      } 
     } 

    } 

那只修复读入数据。如果您尝试在Guid成员上使用.Where(),并且您使用的是BinaryGUID=True,则不会返回任何行(应该有)。目前,您需要BinaryGUID=False,这占用了更多空间,但这是一个简单的解决方案。

如果你能帮助它,尝试,而是定义你的Guid属性:

[Key] 
[MaxLength(16)] 
[MinLength(16)] 
public byte[] AccountUserId { get; set; } 

你将被迫打电话给guidValue.ToByteArray()在应用程序层。您可能可以创建一些帮助程序,而无需调用该功能。拥有用于创建和分析Guid的自定义函数代理可能会有所帮助,因此您可以轻松更改实现。

在我的情况下,我没有奢侈的时间将所有的Guid属性和用法转换为byte[]