降低实体框架生成的查询

时间:2017-04-18 01:25:25

标签: c# sql entity-framework properties ef-code-first

我需要在通过Code First Entity Framework执行函数时小写列名。我试图在this link使用解决方案但它只适用于表映射而不适用于函数映射。

这是我的POCO,用于保存函数执行中的数据。

 public class RBReportInfo
 {
     [Key]
     public int ReportId { get; set; }
     public int ReportDataViewId { get; set; }
 }

这是EF生成的代码,其中fnrbreportinfo是函数名称,@reportId是函数参数。

SELECT 
[Extent1].[ReportId] AS [ReportId], 
[Extent1].[ReportDataViewId] AS [ReportDataViewId]
FROM [dbo].[fnrbreportinfo](@reportId) AS [Extent1]

以下代码执行以填充POCO。

var idParameter = new ObjectParameter("reportId", reportId);
return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<RBReportInfo>(
            $"[{nameof(ReportBuilderContext)}].[fnrbreportinfo](@reportId)", idParameter);

此代码在OnModelCreating()方法中实现,该方法更改属性的大小写以匹配查询中的小写数据库列名称。

        modelBuilder.Properties().Configure(c =>
        { 
            var name = c.ClrPropertyInfo.Name.ToLower();
            c.HasColumnName(name);
        });

因此,我希望EF生成的查询如下所示,其中列名称是小写的。

SELECT 
[Extent1].[reportid] AS [ReportId], 
[Extent1].[reportdataviewid] AS [ReportDataViewId]
FROM [dbo].[fnrbreportinfo](@reportId) AS [Extent1]

我尝试将属性名称更改为小写,但它会破坏C#中属性命名的PascalCase约定。

 public class RBReportInfo
 {
     [Key]
     public int reportid { get; set; }
     public int reportdataviewid { get; set; }
 }

我也尝试过使用这些属性,但也失败了。

[Column("reportid")]
public int ReportId{get;set;}

该要求是因为区分大小写的数据库,因此所有表/函数都是小写的。

2 个答案:

答案 0 :(得分:0)

为什么不设置属性名称而不是情人案例命名属性?

[Table("mytable")]
public class MyTable {

    [Column("firstcolumn")]
    public int firstColumn {get;set}

    [Column("secondcolumn")]
    public string secondColumn {get;set;}

}

它不是解决方案,但你可以添加像这样的自定义方法

public IQueriable<TResult> SelectFromDB<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
{
        return source.SqlQuery(source.Select(selector).ToString().ToLower());
}

然后

using(var context = new DBContext())
{
    context.SomeTable.SelectFromDB(data => data).ToList();
}

答案 1 :(得分:0)

我从来没有尝试过这个,但它看起来很有希望你的情况,我恰好在外面看枫叶现在。 EF允许拦截,因此您可以截取查询,并可能在ToLower()上调用command.CommandText

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);
    }
} 

您可以阅读更多here