سؤال

أنا أستخدم Dapper لصياغة بعض أدوات اختبار التحميل التي تحتاج إلى الوصول إلى قاعدة بيانات PostgreSQL.هذا الإصدار المحدد من PostgreSQL لا يدعم المعرفات الفريدة العمومية (GUIDs) محليًا، لذلك يتم تخزين قيم المعرفات الفريدة العمومية (GUID) كسلاسل مكونة من 32 حرفًا.يتم تحويل القيم إلى سلاسل باستخدام someGuid.ToString("N"), ، يمكن إجراء التحويل مرة أخرى إلى Guid باستخدام new Guid(stringValueFromColumn).

سؤالي هو كيف أجعل Dapper يقرأ السلاسل ويحولها مرة أخرى إلى أدلة؟

لقد حاولت تعديل تعيين DbType لكن ذلك لم ينجح.

هل كانت مفيدة؟

المحلول

ربما تكون أبسط طريقة للقيام بذلك (دون انتظار الأناقة) هي الحصول على خاصية ثانية:

public Guid Foo {get;set;}

public string FooString {
    get { return Foo.ToString("N"); }
    set { Foo = new Guid(value); }
}

وفي الاستعلام الخاص بك، الاسم المستعار للعمود باسم FooString.

وبالطبع فإن هذا يطرح السؤال التالي:هل ينبغي أن يدعم dapper الخصائص الخاصة لهذا النوع من الأشياء؟والذي أقول له:من المحتمل.

نصائح أخرى

أعلم أن هذا سؤال قديم ولكن لأي شخص يتعثر في هذا الموضوع كما فعلت اليوم سأقوم بنشر الحل الخاص بي.

أنا أستخدم MySql ولكن لديه نفس المشكلة منذ أن قمت بتخزين الدليل كسلسلة.لإصلاح التعيين دون الحاجة إلى الاسم المستعار للعمود، استخدمت ما يلي:

public class MySqlGuidTypeHandler : SqlMapper.TypeHandler<Guid>
{
    public override void SetValue(IDbDataParameter parameter, Guid guid)
    {
        parameter.Value = guid.ToString();
    }

    public override Guid Parse(object value)
    {
        return new Guid((string)value);
    }
}

وفي Startup.cs الخاص بي:

public void ConfigureServices(IServiceCollection services)
    {
        SqlMapper.AddTypeHandler(new MySqlGuidTypeHandler());
        SqlMapper.RemoveTypeMap(typeof(Guid));
        SqlMapper.RemoveTypeMap(typeof(Guid?));
    }

هذا سؤال قديم ولكني أشعر أنه يحتاج إلى التحديث حيث أن Dapper يدعم الآن الخصائص الخاصة، والتي أشار إليها مارك في إجابته.

private String UserIDString { get; set; }
public Guid UserID
{
    get
    {
        return new Guid(UserIDString);
    }
    private set
    {
        UserID = value;
    }
}

ثم في SQL، قم بإعطاء عمود المعرف الخاص بك اسمًا مستعارًا لتعيينه إلى الخاصية الخاصة وليس الخاصية الفعلية:

SELECT UserID AS UserIDString FROM....

لقد اخترقت الحل معًا.بقدر ما أستطيع أن أقول، لا توجد طريقة لتوجيه Dapper لإنشاء رمز ربط بديل لنوع معين، لذلك قمت بتعديل GetClassDeserializer طريقة لفرض نوع unbox على السلسلة إذا كانت الخاصية عبارة عن دليل.بعد ذلك قمت بإعادة استخدام الكود الذي يقوم بإنشاء استدعاء مُنشئ للتعدادات.

إليك مقتطف الشفرة المعدل (بدءًا من السطر 761 من المراجعة.rf6d62f91f31a):

// unbox nullable enums as the primitive, i.e. byte etc
  var nullUnderlyingType = Nullable.GetUnderlyingType( item.Info.Type );
  var unboxType = nullUnderlyingType != null && nullUnderlyingType.IsEnum ? nullUnderlyingType : item.Info.Type;
  if( unboxType == typeof(Guid))
  {
    unboxType = typeof (string);
  }
  il.Emit( OpCodes.Unbox_Any, unboxType ); // stack is now [target][target][typed-value]
  if (  ( item.Info.Type == typeof( Guid ) && unboxType == typeof( string ) ) 
        || ( nullUnderlyingType != null && nullUnderlyingType.IsEnum ) )
  {
    il.Emit( OpCodes.Newobj, item.Info.Type.GetConstructor( new[] { nullUnderlyingType ?? unboxType} ) );
  }

  il.Emit( OpCodes.Callvirt, item.Info.Setter ); // stack is now [target]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top