簡體   English   中英

泄漏實體框架的抽象-只是一點點

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM