泄漏实体框架';抽象——只是一点点

本文关键字:一点点 抽象 实体 框架 泄漏 | 更新日期: 2023-09-27 18:28:11

如果我想访问RDBMS特有的功能,该怎么办?有没有一种方法可以将DB特定的SQL注入EF生成的SQL中?

例如,在Oracle12c中,您可以向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';

我的问题是:是否有钩子或接口可以将这些RDBMS专用短语注入EF生成的SQL中?或者必须将以上内容与自定义的Oracle数据库提供程序结合起来?这种类型的事情可能吗?你能给我指一个可以提供指导的博客/书籍/视频/大师吗?

泄漏实体框架';抽象——只是一点点

据我所知,没有办法修改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);
            }
        }

但是我现在还不知道如何获取元数据的类型。