0

我是从ASP.NET升级到ASP.NET Core的许多人之一。ASP.NET核心实体框架SQL查询SELECT

在ASP.NET项目中,我从我DAL做数据库调用,像这样:

var result = context.Database.SqlQuery<Object_VM>("EXEC [sp_Object_GetByKey] @Key", 
     new SqlParameter("@Key", Key)) 
     .FirstOrDefault(); 

return result; 

我的视图模型具有附加字段,我的对象不,如相关的表的聚集。将这些字段包含在数据库/表结构中似乎没有必要,也没有直观的反应。我的存储过程计算所有这些东西,并返回应显示的字段,但不存储。

我看到ASP.NET Core已经删除了这个功能。我试图继续使用存储过程并加载视图模型(因此在数据库中没有实体)。我看到类似以下的选项,但结果我得到“2”,即返回的行数(或另一个神秘结果?)。

using(context) 
{ 
    string cmd = "EXEC [sp_Object_getAll]"; 
    var result = context.Database.ExecuteSQLCommand(cmd); 
} 

但是,这不会起作用,因为context.Database.ExecuteSQLCommand只是为了改变数据库,而不是“选择”。

我也看到下面的解决方案,但代码不会为我编译,因为“set”实际上是set<TEntity>,并且这个viewmodel没有数据库实体。

var result = context.Set().FromSql("EXEC [sp_Object_getAll]"); 

任何帮助非常感谢。

+0

1.您不需要从ASP.NET升级到迁移的ASP.NET Core,您应该如此对待它。升级通常意味着向后兼容,迁移意味着没有这种东西。由于ASP.NET Core是一个完整的重写,并且有明显的差异。 2.)ASP.NET Core没有删除任何东西,因为ASP.NET从来没有ORM。这是实体框架(它是重写:EF核心)。 3.阅读https://github.com/aspnet/EntityFramework/wiki/Roadmap以查看EF Core的限制以及将来要添加哪些功能 – Tseng

+0

尚未实现的功能之一是Ad-Hoc绑定(将SQL绑定到未注册为实体的模型)https://github.com/aspnet/EntityFramework/issues/1862 – Tseng

+0

[原始SQL查询和实体框架核心]的可能重复(http://stackoverflow.com/questions/35305825/raw -sql-queries-and-entity-framework-core) –

回答

1

解决方案:

(每曾国藩的建议)

在GitHub上Entity Framework Issues page,有一个关于这个问题的讨论。一位用户建议使用creating your own class来处理这类请求,另一位用户增加一个additional method,使其运行更平滑。我改变了方法slights接受略有不同的params。

这里是我的适应(差别很小),对于其他人也正在寻找一个解决方案:

方法DAL

public JsonResult GetObjectByID(int ID) 
{ 
    SqlParameter[] parms = new SqlParameter[] { new SqlParameter("@ID", ID) }; 
    var result = RDFacadeExtensions.GetModelFromQuery<Object_List_VM>(context, "EXEC [sp_Object_GetList] @ID", parms); 
    return new JsonResult(result.ToList(), setting); 
} 

其他类

public static class RDFacadeExtensions 
{ 
    public static RelationalDataReader ExecuteSqlQuery(
     this DatabaseFacade databaseFacade, 
     string sql, 
     SqlParameter[] parameters) 
    { 
     var concurrencyDetector = databaseFacade.GetService<IConcurrencyDetector>(); 
     using (concurrencyDetector.EnterCriticalSection()) 
     { 
      var rawSqlCommand = databaseFacade 
       .GetService<IRawSqlCommandBuilder>() 
       .Build(sql, parameters); 

      return rawSqlCommand 
       .RelationalCommand 
       .ExecuteReader(
        databaseFacade.GetService<IRelationalConnection>(), 
        parameterValues: rawSqlCommand.ParameterValues); 
     } 
    } 

    public static IEnumerable<T> GetModelFromQuery<T>(
     DbContext context, 
     string sql, 
     SqlParameter[] parameters) 
     where T : new() 
    { 
     DatabaseFacade databaseFacade = new DatabaseFacade(context); 
     using (DbDataReader dr = databaseFacade.ExecuteSqlQuery(sql, parameters).DbDataReader) 
     { 
      List<T> lst = new List<T>(); 
      PropertyInfo[] props = typeof(T).GetProperties(); 
      while (dr.Read()) 
      { 
       T t = new T(); 
       IEnumerable<string> actualNames = dr.GetColumnSchema().Select(o => o.ColumnName); 
       for (int i = 0; i < props.Length; ++i) 
       { 
        PropertyInfo pi = props[i]; 
        if (!pi.CanWrite) continue; 
        System.ComponentModel.DataAnnotations.Schema.ColumnAttribute ca = pi.GetCustomAttribute(typeof(System.ComponentModel.DataAnnotations.Schema.ColumnAttribute)) as System.ComponentModel.DataAnnotations.Schema.ColumnAttribute; 
        string name = ca?.Name ?? pi.Name; 
        if (pi == null) continue; 
        if (!actualNames.Contains(name)) { continue; } 
        object value = dr[name]; 
        Type pt = pi.DeclaringType; 
        bool nullable = pt.GetTypeInfo().IsGenericType && pt.GetGenericTypeDefinition() == typeof(Nullable<>); 
        if (value == DBNull.Value) { value = null; } 
        if (value == null && pt.GetTypeInfo().IsValueType && !nullable) 
        { value = Activator.CreateInstance(pt); } 
        pi.SetValue(t, value); 
       }//for i 
       lst.Add(t); 
      }//while 
      return lst; 
     }//using dr 
    }