[英]Leaking Entity Framework's abstraction - just a little
如果我想访问RDBMS独有的功能怎么办? 有没有一种方法可以将特定于数据库的SQL注入EF生成的SQL中?
例如,在Oracle 12c中,您可以向DDL和DML添加时间有效性(种类繁多;这里仅使用简单的示例):
这可以用C#很好地建模:
[TemporalAxis("valid_time")]
public class SomeEntity
{
public string SomeField { get; set; }
}
然后与LINQ一起使用
var results = context.SomeEntities
.Where(i => i.SomeField = "some_value")
.AsOfPeriodFor("valid_time", dateVariable);
.AsOfPeriodFor
扩展名可以是这样的:
public static class TemporalExtensions
{
public static IEnumerable<TSource> AsOfPeriodFor<TSource>(this IEnumerable<TSource> source,
string temporalAxis, DateTime asOfDate)
{
// reflect on TSource to ensure it has the correct attribute/value (else degrade/throw)
// do something to source that sets up EF to add the extra clause in the DML
return source;
}
}
而且我猜想DbContext可以在初始化时反映其实体来驱动DDL(我将不得不对此进行更多了解)。
上面的结果是EF将发出以下SQL
DDL(在初始化时):
create table some_table
some_field varchar2(30)
period for valid_time -- Need to inject this at DB Initialize time
);
DML(在查询时):
select
some_field
from
some_table
as of period for valid_time to_timestamp('27-Oct-14') -- and this at query time
where
some_field = 'some_value';
我的问题:是否可以使用钩子或IInterfaces将这些RDBMS专业术语注入EF生成的SQL中? 还是必须将上述内容与自定义Oracle DB Provider结合使用? 这种事情有可能发生吗,您能否指出我可以提供指导的博客/书籍/视频/专家?
据我所知,无法修改由EF提供程序生成的SQL。
但是,对于那些特殊情况,您可以直接运行SQL。
context.Database.SqlQuery<SomeEntity>("select * from SomeEntity " +
"some more custom sql here " +
"where somecomlumn = @p1", parameter1);
您只需要确保返回的任何内容都与SomeEntity的形状匹配即可。
实施拦截器: EF教程
看起来像这样:
class EFCommandInterceptor: IDbCommandInterceptor
{
public void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
LogInfo("NonQueryExecuted", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText));
}
public void NonQueryExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
LogInfo("NonQueryExecuting", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText));
}
public void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContextt<System.Data.Common.DbDataReader> interceptionContext)
{
LogInfo("ReaderExecuted", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText));
}
public void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
LogInfo("ReaderExecuting", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText));
}
public void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
LogInfo("ScalarExecuted", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText));
}
public void ScalarExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
LogInfo("ScalarExecuting", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText));
}
private void LogInfo(string command, string commandText)
{
Console.WriteLine("Intercepted on: {0} :- {1} ", command, commandText);
}
}
但是如何获取类型以获取元数据,我现在还不知道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.