服务结构参与者的静态 class 配置
static class configuration for service fabric actors
Service fabric actors 用于访问数据库,所有方法都假设使用 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() 或如下所示的主要方法时声明上面的静态方法:
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;
}
}
我通常不想回答我自己的问题,但这是我到目前为止发现的。
首先,如果我想让解决问题的实际解决方案与标题本身更相关,也许我需要更改这个问题的标题。然而,由于标题问题已经用这个 post 回答了,所以我将保持原样。
为了给出简短的答案,静态 class 配置可以在我上面提到的所有地方完成,例如 Actor 构造函数、OnActivateAsync() 等,因为静态 class 仍然共享AppDomain 中的不同线程(Actor 都是单个独立线程)(Actor 在 AppDomain 中 运行。如果我错了请纠正我。)
真正导致上述问题的原因是因为使用Dapper的映射定义被声明为动态的;如下所示:
return sqlConnection.Query<dynamic>(some_sql_script, new { objInstance }).FirstOrDefault();
一旦将预期的 return 类型 T 更改为包含 typeHandler 类型的强类型,Dapper 就会正确调用 typeHandler:
return sqlConnection.Query<StrongType>(some_sql_script, new { objInstance }).FirstOrDefault();
Service fabric actors 用于访问数据库,所有方法都假设使用 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() 或如下所示的主要方法时声明上面的静态方法:
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;
}
}
我通常不想回答我自己的问题,但这是我到目前为止发现的。
首先,如果我想让解决问题的实际解决方案与标题本身更相关,也许我需要更改这个问题的标题。然而,由于标题问题已经用这个 post 回答了,所以我将保持原样。
为了给出简短的答案,静态 class 配置可以在我上面提到的所有地方完成,例如 Actor 构造函数、OnActivateAsync() 等,因为静态 class 仍然共享AppDomain 中的不同线程(Actor 都是单个独立线程)(Actor 在 AppDomain 中 运行。如果我错了请纠正我。)
真正导致上述问题的原因是因为使用Dapper的映射定义被声明为动态的;如下所示:
return sqlConnection.Query<dynamic>(some_sql_script, new { objInstance }).FirstOrDefault();
一旦将预期的 return 类型 T 更改为包含 typeHandler 类型的强类型,Dapper 就会正确调用 typeHandler:
return sqlConnection.Query<StrongType>(some_sql_script, new { objInstance }).FirstOrDefault();