如何在 Entity Framework 6 中使用 DbDataReader 获取 table 名称?
How to get table name using DbDataReader in Entity Framework 6?
我的应用程序中有一个自定义 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 方法 returns 一个难以理解的结果,其中 TableName 属性 等于“SchemaTable”。我在这里做错了什么以及如何获得正确的 table 名称(如“用户”)。
注意:我不使用 SqlCommand 和 SqlCommand.ExecuteReader 来执行查询。我只是使用 dbSet。即 dbContext.Users.Where(x => x.Id = 1).Single();
TableName
属性 将始终 return "SchemaTable"
,因为没有其他有意义的名称可以 return.
根据 the link you found,每个列的 table 名称应该 return 编辑在架构 table 的 BaseTableName
列中。但是如果指定了 CommandBehavior.KeyInfo
标志,这只会被 returned。
通过源代码挖掘,看起来你需要使用 ReaderExecuting
方法并接管执行命令的责任才能做到这一点:
public override void ReaderExecuting(
DbCommand command,
DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
// Skip processing for a specific database:
if (command.Connection.Database.Equals("...")) return;
var commandBehavior = interceptionContext.CommandBehavior | CommandBehavior.KeyInfo;
try
{
var reader = command.ExecuteReader(commandBehavior);
var result = new MyDbDataReader(command.Connection.Database, reader);
interceptionContext.Result = result;
}
catch (Exception ex)
{
interceptionContext.Exception = ex;
}
}
理论上您应该能够从架构 table:
中提取 BaseTableName
列
public override DateTime GetDateTime(int ordinal)
{
var schemaTable = base.GetSchemaTable();
var tableName = schemaTable.Rows[ordinal].Field<string>("BaseTableName");
...
}
我的应用程序中有一个自定义 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 方法 returns 一个难以理解的结果,其中 TableName 属性 等于“SchemaTable”。我在这里做错了什么以及如何获得正确的 table 名称(如“用户”)。
注意:我不使用 SqlCommand 和 SqlCommand.ExecuteReader 来执行查询。我只是使用 dbSet。即 dbContext.Users.Where(x => x.Id = 1).Single();
TableName
属性 将始终 return "SchemaTable"
,因为没有其他有意义的名称可以 return.
根据 the link you found,每个列的 table 名称应该 return 编辑在架构 table 的 BaseTableName
列中。但是如果指定了 CommandBehavior.KeyInfo
标志,这只会被 returned。
通过源代码挖掘,看起来你需要使用 ReaderExecuting
方法并接管执行命令的责任才能做到这一点:
public override void ReaderExecuting(
DbCommand command,
DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
// Skip processing for a specific database:
if (command.Connection.Database.Equals("...")) return;
var commandBehavior = interceptionContext.CommandBehavior | CommandBehavior.KeyInfo;
try
{
var reader = command.ExecuteReader(commandBehavior);
var result = new MyDbDataReader(command.Connection.Database, reader);
interceptionContext.Result = result;
}
catch (Exception ex)
{
interceptionContext.Exception = ex;
}
}
理论上您应该能够从架构 table:
中提取BaseTableName
列
public override DateTime GetDateTime(int ordinal)
{
var schemaTable = base.GetSchemaTable();
var tableName = schemaTable.Rows[ordinal].Field<string>("BaseTableName");
...
}