我将ASP.NET Core用于Azure App Service应用程序的后端。对于数据库中的每个表,我创建一个控制器,该控制器充当该表的API端点。代码没有问题,但是对于每个控制器,除了Include(m => m.<Property>)
外,我都重复相同的逻辑。有没有一种方法可以将所有这些逻辑移到父TableController
类中,并在模型类中包含Include()
方法。
这些是一些示例文件:
表控制器(所有API控制器的父类):
使用System.Threading.Tasks; 使用Microsoft.AspNetCore.Mvc;
namespace Backend.API
{
public abstract class TableController<T> : Controller
{
// Public Methods
[HttpGet]
[Route("")]
public abstract Task<IActionResult> GetAllAsync();
[HttpPost]
[Route("")]
public abstract Task<IActionResult> CreateAsync([FromBody] T created);
[HttpGet]
[Route("{id}")]
public abstract Task<IActionResult> GetAsync(string id);
[HttpPatch]
[Route("{id}")]
public abstract Task<IActionResult> UpdateAsync(string id, [FromBody] T updated);
[HttpDelete]
[Route("{id}")]
public abstract Task<IActionResult> DeleteAsync(string id);
}
}
示例模型:
using System;
using System.ComponentModel.DataAnnotations;
namespace Backend.Models.DB
{
public class BlogPost
{
// Public Properties
public DateTime DatePublished { get; set; }
public Guid Id { get; set; }
[Required]
public string Body { get; set; }
[Required]
public string Title { get; set; }
public string DatePublishedString =>
string.Format("Posted on {0}.", DatePublished.ToString().ToLower());
[Required]
public User Publisher { get; set; }
// Constructors
public BlogPost() : this(null, null, null, new DateTime()) { }
public BlogPost(BlogPost post) :
this(post.Title, post.Body, post.Publisher, post.DatePublished) { }
public BlogPost(string title, string body, User publisher, DateTime datePublished)
{
Title = title;
if (datePublished == new DateTime())
DatePublished = DateTime.Now;
else
DatePublished = datePublished;
Body = body;
Publisher = publisher;
}
// Public Methods
public void Update(BlogPost updated)
{
Body = updated.Body;
Title = updated.Title;
}
}
}
示例控制器:
using System;
using System.Threading.Tasks;
using Backend.Models.DB;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace Backend.API
{
[Route("tables/BlogPost")]
public class BlogPostController : TableController<BlogPost>
{
// Private Properties
private readonly BadmintonClubDBDataContext _db;
// Constructors
public BlogPostController(BadmintonClubDBDataContext db) => _db = db;
// Overridden Methods
public override async Task<IActionResult> GetAllAsync()
{
var posts = await _db.BlogPosts
.Include(bp => bp.Publisher)
.ToArrayAsync();
return Json(posts);
}
public override async Task<IActionResult> CreateAsync([FromBody] BlogPost created)
{
if (!ModelState.IsValid)
return BadRequest();
BlogPost post = (await _db
.AddAsync(new BlogPost(created))).Entity;
await _db.SaveChangesAsync();
return Json(post);
}
public override async Task<IActionResult> GetAsync(string id)
{
BlogPost post = await _db.BlogPosts
.Include(bp => bp.Publisher)
.SingleOrDefaultAsync(bp => bp.Id == new Guid(id));
if (post == null)
return NotFound();
return Json(post);
}
public override async Task<IActionResult> UpdateAsync(string id, [FromBody] BlogPost updated)
{
BlogPost post = await _db.BlogPosts
.Include(bp => bp.Publisher)
.SingleOrDefaultAsync(bp => bp.Id == new Guid(id));
if (post == null)
return NotFound();
if (post.Id != updated.Id || !ModelState.IsValid)
return BadRequest();
post.Update(updated);
await _db.SaveChangesAsync();
return Json(post);
}
public override async Task<IActionResult> DeleteAsync(string id)
{
BlogPost post = await _db.BlogPosts
.FindAsync(id);
if (post == null)
return NotFound();
_db.BlogPosts.Remove(post);
await _db.SaveChangesAsync();
return Ok();
}
}
}
看着示例控制器,我已经通过Update()
之类的方法和构造函数将大多数逻辑移到了模型中。如何将Include()
方法的逻辑也移到模型中?
感谢所有帮助。
答案 0 :(得分:0)
使用实体的func表达式参数声明方法,它将允许您在调用方法时传递lambda表达式
public ICollection<TData> FindAll<TInclude>(Expression<Func<TData, TInclude>> include)
{
using (var ctx = new TContext())
{
return ctx.T.Include(include).ToList();
}
}
然后可以按以下方式调用方法
var entityWithNavigationProp = FindAll(entity=>entity.propertyName);
有关详细信息,请查看How to notify parent component of change and refresh view