Can I scaffold a controller and view based on a SQL query or stored procedure? (in ASP.NET Core MVC with EF Core)

huangapple go评论89阅读模式
英文:

Can I scaffold a controller and view based on a SQL query or stored procedure? (in ASP.NET Core MVC with EF Core)

问题

我可以在Visual Studio中使用脚手架功能吗?其中的模型是基于SQL查询或存储过程而不是数据库表的?

这部分是出于懒惰/效率的考虑,也是为了了解EF Core和VS脚手架的限制...因此,我还想了解推荐的替代方法。

我将生成一系列的报表,从各个表中选择聚合列,并进行时间段过滤,所有这些报表都将显示在ASP.NET Core MVC Web应用程序中。

我更喜欢将SQL编写为实际的SQL,而不是使用Linq-to-SQL,但两者都是可选的。对于SQL是在Web应用程序中执行的字符串、存储过程还是SQL视图,我也不在意。

我意识到我可以手动生成模型、控制器和视图代码,并执行SQL并将其投影为匿名类型。但那感觉要打很多字!

DbContext中是否可以有一个DBSet<TimeReport> TimeReports,并且该实体基于SQL以便进行脚手架生成?

我目前的工作思路是为每个报表创建一个SQL视图,并在DbContext中有一个DBSet<TimeReportView> TimeReports,但我还没有尝试过这种方法。

英文:

Can I make use of the scaffolding feature in Visual Studio where the model is based on a SQL query or stored procedure rather than a database table?

https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-controller?view=aspnetcore-7.0&amp;tabs=visual-studio

This is in part fuelled by laziness/efficiency but also to understand the limitations of EF Core & VS scaffolding... Therefore I would also like to find out about recommended alternative approaches.

I will be generating a bunch of reports selecting aggregate columns from various tables with time period filtering, all to be displayed within the ASP.NET Core MVC web app.

I would prefer writing the SQL as actual SQL rather than fumble around with Linq-to-SQL but either is an option. I'm also not bothered if the SQL is a string executed in the web app or a stored procedure or even a SQL view.

I realise that I could manually generate the model, controller and view code and execute the SQL and project it as an anonymous type. But that feels like a lot of typing!

Would it be possible to have in the DbContext a DBSet&lt;TimeReport&gt; TimeReports and have that entity based on SQL so as to facilitate scaffolding?

My current working idea is to create a SQL view per report and have in the DbContext a DBSet&lt;TimeReportView&gt; TimeReports but haven't yet tried this.

答案1

得分: 0

我意识到这是我问的一个相当愚蠢的问题...

为什么呢?- VS脚手架在运行时并不真正知道你在DbContext中定义的数据库表是否存在,直到它尝试在运行时使用它。

因此,你可以创建一个包含任何属性的模型类...

  1. 在你的DbContext中放置一个DbSet<TMyFakeModel>
  2. 利用脚手架来节省输入
  3. 在你的DbContext中移除DbSet<TMyFakeModel>
  4. 更新脚手架生成的控制器,从其他来源(如Linq to Sql、存储过程等)检索你的模型

例如,将控制器中的脚手架代码更改为...

  1. // GET: StaffTimeReport
  2. public async Task<IActionResult> Index()
  3. {
  4. return _context.StaffTimeReport != null ?
  5. View(await _context.StaffTimeReport.ToListAsync()) :
  6. Problem("Entity set 'AdminContext.StaffTimeReport' is null.");
  7. }

改为像这样...

  1. // GET: StaffTimeReport
  2. public async Task<IActionResult> Index()
  3. {
  4. var response =
  5. (
  6. from staff in _context.Users
  7. join sessions in _context.Sessions on staff.UserId equals sessions.UserId
  8. group new { staff, sessions } by new { staff.UserId, staff.FirstName, staff.Surname } into g
  9. //project to model that was scaffolded
  10. select new StaffTimeReport
  11. {
  12. UserId = g.Key.UserId,
  13. FirstName = g.Key.FirstName,
  14. Surname = g.Key.Surname ,
  15. Points = g.Sum(g=>g.sessions.Points),
  16. Sessions = g.Count(),
  17. TimeSpent = g.Sum(g => g.sessions.SessionLength)
  18. }
  19. )
  20. .ToList();
  21. return View(response);
  22. }
英文:

I realise now that this was a pretty dumb question for me to ask...

Why? - VS scaffolding doesn't really know if you have a DB table as defined in a DbContext until it tries to make use of it in runtime.

Therefore you can create a Model class containing whatever properties you want...

  1. Put a DbSet&lt;TMyFakeModel&gt; in your DbContext
  2. Leverage Scaffolding to save on typing
  3. Remove DbSet&lt;TMyFakeModel&gt; in your DbContext
  4. Update Scaffolded Controller to retrieve your Models from an alternative source such as Linq to Sql, Stored Procedure etc...

E.g. Change scaffolded code in Controller...

  1. // GET: StaffTimeReport
  2. public async Task&lt;IActionResult&gt; Index()
  3. {
  4. return _context.StaffTimeReport != null ?
  5. View(await _context.StaffTimeReport.ToListAsync()) :
  6. Problem(&quot;Entity set &#39;AdminContext.StaffTimeReport&#39; is null.&quot;);
  7. }

To something like this instead...

  1. // GET: StaffTimeReport
  2. public async Task&lt;IActionResult&gt; Index()
  3. {
  4. var response =
  5. (
  6. from staff in _context.Users
  7. join sessions in _context.Sessions on staff.UserId equals sessions.UserId
  8. group new { staff, sessions } by new { staff.UserId, staff.FirstName, staff.Surname } into g
  9. //project to model that was scaffolded
  10. select new StaffTimeReport
  11. {
  12. UserId = g.Key.UserId,
  13. FirstName = g.Key.FirstName,
  14. Surname = g.Key.Surname ,
  15. Points = g.Sum(g=&gt;g.sessions.Points),
  16. Sessions = g.Count() ,
  17. TimeSpent = g.Sum(g =&gt; g.sessions.SessionLength)
  18. }
  19. )
  20. .ToList();
  21. return View(response);
  22. }

huangapple
  • 本文由 发表于 2023年7月27日 16:44:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76777995.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定