. net核心实体框架存储过程

本文关键字:存储过程 框架 实体 核心 net | 更新日期: 2023-09-27 18:16:11

我正在尝试移植一个ASP。.NET 4.5应用程序到。NET Core,我有一个真正的问题,我似乎不能弄清楚。

我现有的应用程序执行存储过程,返回具有多个数据表的数据集。实体框架可以自动将返回的字段映射到我的实体属性,但只适用于数据集中的第一个数据表(自然)。

所以我只是想弄清楚是否有可能以某种方式拦截模型构建过程并使用自定义代码来处理数据集并查看其他数据表以设置实体字段。

我知道我可以使用直接使用SqlConnection执行存储过程的正常方式,但我想知道实体框架是否已经有一些方法可以做到这一点。

. net核心实体框架存储过程

目前,执行返回数据的存储过程的方法是使用DbSet.FromSql方法。

using (var context = new SampleContext())
{
    var data= context.MyEntity
        .FromSql("EXEC GetData")
        .ToList();
}

这有一定的局限性:

  • 必须在DbSet
  • 上调用
  • 返回的数据必须映射到DbSet类型
  • 上的所有属性
  • 不支持ad hoc对象

或者您可以退回到普通ADO。净:

using (var context = new SampleContext())
using (var command = context.Database.GetDbConnection().CreateCommand())
{
    command.CommandText = "GetData";
    command.CommandType = CommandType.StoredProcedure;
    context.Database.OpenConnection();
    using (var result = command.ExecuteReader())
    {
        // do something with result
    }
}

计划在某个阶段引入对从SQL查询返回临时类型的支持。

普通ADO。NET代码将如下所示来使用存储过程。通过使用dataadapter:

            DataSet dataSet = null;
            using (var context = new SampleContext())
            using (var command = context.Database.GetDbConnection().CreateCommand())
            {
                command.CommandText = "GetData";
                command.CommandType = CommandType.StoredProcedure;
                context.Database.OpenConnection();
                using (SqlDataAdapter adapter = new SqlDataAdapter())
                {
                    adapter.SelectCommand = command;
                    dataSet = new DataSet();
                    adapter.Fill(dataSet);
                    return dataSet;
                }
            } 

要回答@DKhanaf使用多个数据集的问题,您可以使用SqlDataAdapter用所有结果集填充DataSet对象。SqlDataAdapter需要完整的。net框架,所以你必须运行你的。net core项目,同时瞄准。net 462或类似的东西。

         using (var context = new SampleContext())
            using (var command = context.Database.GetDbConnection().CreateCommand())
            {
                command.CommandText = "GetData";
                command.CommandType = CommandType.StoredProcedure;
                context.Database.OpenConnection();
                using (SqlDataAdapter adapter = new SqlDataAdapter(command))
                {
                    var ds = new DataSet();
                    adapter.Fill(ds);
                    return ds;
                }
            }
        }

我使用了https://github.com/verdie-g/StoredProcedureEFCore,EnterpriseLibrary.Data.NetCore,EFCor.SqlServer,EFCore.Tools的StoredProcedureEFCore内核包

我尝试了DbFirst方法与{存储库模式}..我想是的

startup.cs

ConfigureServices(IServiceCollection services){
    services.AddDbContext<AppDbContext>(opt => opt
                   .UseSqlServer(Configuration.GetConnectionString("SampleConnectionString")));
    services.AddScoped<ISomeDAL, SomeDAL>();
}
            
    public  class AppDbContext : DbContext{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {}
}

ISomeDAl接口有{GetPropertiesResponse GetAllPropertiesByCity(int CityId);}

public class SomeDAL : ISomeDAL
{
     private readonly AppDbContext context;
     public SomeDAL(AppDbContext context)
         {
             this.context = context;
         }
     public  GetPropertiesResponse GetAllPropertiesByCity(int CityId)
     {
         //Create Required Objects for response 
         //wont support ref Objects through params
         context.LoadStoredProc(SQL_STATEMENT)
            .AddParam("CityID", CityId).Exec( r =>
             {
                  while (r.Read())
                  {
                       ORMapping<GenericRespStatus> orm = new  ORMapping<GenericRespStatus>();
                       orm.AssignObject(r, _Status);
                  }
                  if (r.NextResult())
                  {
                       while (r.Read())
                       {
                           Property = new Property();
                           ORMapping<Property> orm = new ORMapping<Property>();
                           orm.AssignObject(r, Property);
                           _propertyDetailsResult.Add(Property);
                       }
                  }    
           });
    return new GetPropertiesResponse{Status=_Status,PropertyDetails=_propertyDetailsResult}; 
    }
}
public class GetPropertiesResponse
{
     public GenericRespStatus Status;
     public List<Property> PropertyDetails;
     public GetPropertiesResponse()
         {
             PropertyDetails = new List<Property>();
         }
}
public class GenericRespStatus
{
     public int ResCode { get; set; }
     public string ResMsg { get; set; }
}
internal class ORMapping<T>
{
    public void AssignObject(IDataReader record, T myClass)
    {
        PropertyInfo[] propertyInfos = typeof(T).GetProperties();
        for (int i = 0; i < record.FieldCount; i++)
        {
            if (propertyInfos.Any(obj => obj.Name == record.GetName(i))) //&& record.GetValue(i) != DBNull.Value
            {
                propertyInfos.Single(obj => obj.Name == record.GetName(i)).SetValue(myClass, Convert.ChangeType(record.GetValue(i), record.GetFieldType(i)));
            }
        }
    }
}