1

Service Fabric Actor 用于访问数据库,所有方法都假设使用 Dapper 作为 ORM 工具。

我发现作为解决当前问题的最佳方法的一件事是在 Dapper 中使用称为 SqlMapper 的东西。这样,您可以定义处理某些数据类型的一般行为,例如:

SqlMapper.AddTypeHandler(new DateTimeHandler());

public class DateTimeHandler : SqlMapper.TypeHandler<DateTime>
{
    public override void SetValue(IDbDataParameter parameter, DateTime dateTime)
    {
        parameter.Value = dateTime.ValidateDateTime();
    }

    public override DateTime Parse(object value)
    {
        return ((DateTime)value).ValidateDateTime();
    }
}

当您使用 DateTimeHandler 等自定义处理程序声明上述静态方法 (AddTypeHandler) 时,使用 Dapper 框架完成的映射将确保任何 dateTime 类型正确通过上述处理程序。

我希望看到这种情况发生在每个 Actor 通过 Dapper 与数据库通信时。我还没有看到它在尝试使用几个不同的地方(例如 Actor constructor() 或 main 方法,如下所示)声明上述静态方法:

private static void Main()
{
        try
        {
            // This line registers an Actor Service to host your actor class with the Service Fabric runtime.
            // The contents of your ServiceManifest.xml and ApplicationManifest.xml files
            // are automatically populated when you build this project.
            // For more information, see https://aka.ms/servicefabricactorsplatform

            ActorRuntime.RegisterActorAsync<SqlRepositoryActor>(
               (context, actorType) => new ActorService(context, actorType)).GetAwaiter().GetResult();

            // This doesn't seem like a right place as I don't see the handler being called when Actor uses dapper mapping methods.
            SqlMapper.AddTypeHandler(new DateTimeHandler());

            Thread.Sleep(Timeout.Infinite);
        }
        catch (Exception e)
        {
            ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
            throw;
        }
} 
4

1 回答 1

0

我通常不想回答我自己的问题,但这是我迄今为止发现的。

首先,如果我希望解决问题的实际解决方案与标题本身更相关,也许我需要更改这个问题的标题。但是,由于这篇文章回答了标题问题,我将保持原样。

简而言之,静态类配置可以在我上面提到的所有地方完成,例如 Actor 构造函数、OnActivateAsync() 等,因为静态类仍然在 AppDomain 内的不同线程之间共享(Actor 都是单个独立线程) (并且演员在 AppDomain 内运行。如果我错了,请纠正我。)

实际导致上述问题的原因是使用 Dapper 的映射定义被声明为动态的;如下图:

return sqlConnection.Query<dynamic>(some_sql_script, new { objInstance }).FirstOrDefault();

一旦将预期的返回类型 T 更改为包含 typeHandler 类型的强类型,Dapper 就会正确调用 typeHandler:

return sqlConnection.Query<StrongType>(some_sql_script, new { objInstance }).FirstOrDefault();
于 2019-12-20T17:07:44.280 回答