Asp.net core 具有自定义模型的实体框架核心原始SQLQueries
使用EntityFramework6,我能够使用执行原始SQL查询,并使用DBContext中未定义的自定义模型来存储查询的输出。下面是一个简单的例子:Asp.net core 具有自定义模型的实体框架核心原始SQLQueries,asp.net-core,entity-framework-core,asp.net-core-2.0,Asp.net Core,Entity Framework Core,Asp.net Core 2.0,使用EntityFramework6,我能够使用执行原始SQL查询,并使用DBContext中未定义的自定义模型来存储查询的输出。下面是一个简单的例子: List<MyModel> data = context.Database.SqlQuery<MyModel>("SELECT Orders.OrderID, Customers.CustomerName FROM Orders INNER JOIN Customers ON Orders.CustomerID=Cust
List<MyModel> data = context.Database.SqlQuery<MyModel>("SELECT Orders.OrderID, Customers.CustomerName FROM Orders INNER JOIN Customers ON Orders.CustomerID=Customers.CustomerID;").ToList();
此查询通知EntityFramework核心,查询将返回一个图书列表。有没有一种方法可以在Entity Framework Core中实现类似的功能?来自.NET Core 2.1:
modelBuilder.Query()
context.Query().FromSql(rawSql)
获取数据问题是关于.NETCore2的。现在我有了一个解决方案,我将把它写在这里,以便其他人可以使用它,以防他/她需要它 首先,我们在dbContext类中添加以下方法
public List<T> ExecSQL<T>(string query)
{
using (var command = Database.GetDbConnection().CreateCommand())
{
command.CommandText = query;
command.CommandType = CommandType.Text;
Database.OpenConnection();
List<T> list = new List<T>();
using (var result = command.ExecuteReader())
{
T obj = default(T);
while (result.Read())
{
obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
if (!object.Equals(result[prop.Name], DBNull.Value))
{
prop.SetValue(obj, result[prop.Name], null);
}
}
list.Add(obj);
}
}
Database.CloseConnection();
return list;
}
}
公共列表ExecSQL(字符串查询)
{
使用(var command=Database.GetDbConnection().CreateCommand())
{
command.CommandText=查询;
command.CommandType=CommandType.Text;
OpenConnection();
列表=新列表();
使用(var result=command.ExecuteReader())
{
T obj=默认值(T);
while(result.Read())
{
obj=Activator.CreateInstance();
foreach(obj.GetType().GetProperties()中的PropertyInfo属性)
{
如果(!object.Equals(结果[prop.Name],DBNull.Value))
{
属性设置值(对象,结果[属性名称],null);
}
}
列表。添加(obj);
}
}
CloseConnection();
退货清单;
}
}
现在我们可以得到以下代码
List<Customer> Customers = _context.ExecSQL<Customer>("SELECT ......");
List Customers=\u context.ExecSQL(“选择…”);
以下是我是如何让它工作的(为了完整性):
MyModel.cs:
公共类MyModel
{
//SQL将返回的列
公共双精度?A{get;set;}
公共双精度B{get;set;}
}
添加刚从原始EF上下文类继承的类(我称为My DbContextBase):
公共类DbContext:DbContextBase
{
公共虚拟数据库集MyModels{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
//必要,因为我们的模型不是EF模型
modelBuilder.Entity(Entity=>
{
entity.HasNoKey();
});
}
}
使用该类(而不是原始EF上下文类):
//使用新的db子类
使用(var db=new DbContext())
{
var models=await db.MyModels.FromSqlRaw(…).ToListSync();//例如:“从苹果A选择*在A.col=B.col上加入香蕉B”
}
注:
- 如果需要,只需使用
而不是FromSqlInterpolated
FromSqlRaw
- “db context”子类允许您在不影响“polyfill”代码的情况下更新EF模型
- 使用仅返回1个结果集的SQL Server存储过程
public class MyCustomModel
{
public string Text { get; set; }
public int Count { get; set; }
}
将其添加到您自己的DbContext中
为您的自定义模型创建DbSet
public virtual DbSet<MyCustomModel> MyCustomModelName { get; set; }
公共虚拟数据库集MyCustomModelName{get;set;}
请记住,指定自定义模型没有键
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
...
modelBuilder.Entity<MyCustomModel>().HasNoKey();
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
基于模型创建(modelBuilder);
...
modelBuilder.Entity().HasNoKey();
}
从dbContext实例中使用它
异步公共任务GetMyCustomData()
{
var rv=新列表();
使用(var dataContext=new DbContext())
{
var sql=@”
选择文本字段为“文本”,计数(1)为“计数”
来自MyTable”;
rv=wait dataContext.Set().FromSqlRaw(sql).toListSync();
}
返回rv;
}
还没有。最终将有可能在未来的EFC版本中发布。请参阅和。谢谢您的回复。所以我不得不等待这个未来。更多关于这个特性的信息在这里:这只是普通的ADO.Net。这并不是说它不起作用,而是我想知道为什么在EF core现在有内置解决方案的情况下,您会提出它。添加generic Activator.CreateInstance()的速度非常慢,如果查询大型数据集,它会快速复合。如果您追求的是性能,请查看Dapper以获得完整的解决方案,或者从DbDataReader手动创建模型实例(不太好)。整个应用程序都基于EF,因此我必须使用EF。我知道大量记录的问题,但我们在所有查询中都使用分页,因此不可能有超过100条记录。答案不值得向下投票=)基本上EF中缺少自定义查询支持。core,我们的架构中有外部视图,我们在其上执行连接和自定义查询,我们不能只添加自定义数据库集,因为它不受支持,所以我们使用simular,只使用automapper和更好的缓存解决方案。这个解决方案的问题是缺少缓存,比如getProperties相当重,您可以用编译后的表达式替换ActivatorCreateInstance。AutoMapper基本上已经完成了所有的脏活。谢谢,但这不会导致数据库中的表基于
YourModel
生成吗?我有一个带有productname和quantity的自定义类。使用与在EF5.x中有效的提问相同的技巧。我在.Net标准2.0类库中有EF核心:-SHad想修改我的问题但做得很好Martin!我可以确认,这个也可以。你需要将这个添加到你的模型中吗?我想我会用整洁的方式。。。通常情况下,您只需要在自定义sql查询中选择字段的子集。这应该是可能的,而无需将其添加到您的模型中。。。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
...
modelBuilder.Entity<MyCustomModel>().HasNoKey();
}
async public Task<List<MyCustomModel>> GetMyCustomData()
{
var rv = new List<MyCustomModel>();
using (var dataContext = new DbContext())
{
var sql = @"
select textField as 'Text', count(1) as 'Count'
from MyTable";
rv = await dataContext.Set<MyCustomModel>().FromSqlRaw(sql).ToListAsync();
}
return rv;
}