【发布时间】:2021-11-16 02:22:02
【问题描述】:
我的应用程序中有一个自定义 DbDataReader,它会覆盖 GetDateTime 方法来更改 DateTimeKind。
public class MyDbDataReader : BaseDbDataReader
{
private string _dbName;
public MyDbDataReader(string dbName, DbDataReader source) : base(source)
{
_dbName = dbName;
}
public override DateTime GetDateTime(int ordinal)
{
var tableName = base.GetSchemaTable().TableName; //this doesn't work
return DateTime.SpecifyKind(base.GetDateTime(ordinal), base.GetName(ordinal).EndsWith("UTC", StringComparison.OrdinalIgnoreCase) ? DateTimeKind.Utc : DateTimeKind.Local);
}
}
这是我的 BaseDbDataReader:
public abstract class BaseDbDataReader : DbDataReader
{
readonly DbDataReader source;
public BaseDbDataReader(DbDataReader source)
{
this.source = source;
}
...
public override DataTable GetSchemaTable() { return source.GetSchemaTable(); }
}
这个 dbReader 用在我的自定义拦截器中:
public class MyInterceptor : DbCommandInterceptor
{
public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
base.ReaderExecuted(command, interceptionContext);
if (!command.Connection.Database.Equals("...") &&
!(interceptionContext.Result is MyDbDataReader) &&
interceptionContext.Result != null &&
interceptionContext.Exception == null)
{
interceptionContext.Result = new MyDbDataReader(command.Connection.Database, interceptionContext.Result);
}
}
}
我想要的只是在 GetDateTime 方法中获取 TableName。但是 GetSchemaTable 方法返回一个难以理解的结果,其中 TableName 属性等于“SchemaTable”。我在这里做错了什么以及如何获得正确的表名(如“用户”)。
注意:我不使用 SqlCommand 和 SqlCommand.ExecuteReader 来执行查询。我只是使用 dbSet。即dbContext.Users.Where(x => x.Id = 1).Single();
【问题讨论】:
-
EF Core 使用 DbDataReader,而不是相反。你想做什么?也许更改加载日期的
DateTimeKind? There are far simpler solutions。该问题终于在 EF Core 2.1 及更高版本中得到解决 -
@PanagiotisKanavos,我无法迁移到 EF 核心。并且提供的解决方案不适用于我的情况。因为
((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized事件仅在创建 EF 模型(来自 dbContext 的模型)时有效。但在将 IQueryable 映射到匿名类型或任何其他不被 EF 跟踪的模型时,它不起作用。示例:1)dbContext.Users.Where(x=>x.IsActive).ToArray()- 此代码将触发 ObjectMaterialized 事件。 2)dbContext.Users.Where(x=>x.IsActive).Select(ToCustomModel).ToArray()- 此代码不会触发 ObjectMaterialized 事件 -
EF 也使用 DbDataReader。版本无所谓。所有更高级别的数据库都使用 ADO.NET 的 DbDataReader。您无需创建自定义来更改 DateTimeKind。无论如何,ORM不会使用您的自定义 DbDataReader,它们将使用数据库提供程序的类。转换类型是类型转换器的工作
-
但无论如何,在我的情况下,具有 DateTimeKind 属性的解决方案将不起作用。我的目标是更改加载日期的 DateTimeKind。但不适用于所有日期时间。我只想为特定的 dateTime 属性更改它。
标签: c# asp.net entity-framework entity-framework-6