2016-10-12 27 views
1

私はそれはお勧めではありませんが、時には動作する必要があるものを継承することもあります。このケースでは、PKのためのガイドです。System.Data.SqliteでGUIDを主キーとして使用する方法

デフォルトでは、System.Guidはバイト[](またはBinaryGUID = Falseを使用している場合はString)で動作しないというエラーが表示されます。

答えて

1

これを修正するには、byte []配列(または文字列)を代行受信し、代わりにGuidタイプを返す必要があります。これはSystem.Data.Sqliteプロバイダーで可能です。その後

まず

using System.Data.SQLite; 

、あなたのコード-最初デシベルコンテキストのコンストラクタでこれを置く:

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プロパティを定義します。あなたはあなたのアプリケーション層でguidValue.ToByteArray()を呼び出すことを余儀なくされるでしょう

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

。あなたは、あなたがその機能を呼び出す必要がないいくつかのヘルパーを作成することができるかもしれません。 Guidsの作成と解析に独自のカスタム関数プロキシを使用すると、実装を簡単に変更できます。

私の場合、Guidのすべてのプロパティと使用法をbyte[]

に変換する時間の贅沢はありません
関連する問題