如何减少控制器中的冗余?

问题描述 投票:-1回答:1

我使用ASP.NET Core作为Azure App Service应用程序的后端。对于数据库中的每个表,我创建了一个控制器,它充当该表的API端点。代码没有问题但是对于每个Controller,我重复相同的逻辑,除了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()方法的逻辑也移动到我的模型中?

我感谢所有的帮助。

asp.net-core code-design
1个回答
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);

有关详细信息,请查看Pass a lambda parameter to an include statement

并为表达检查this

© www.soinside.com 2019 - 2024. All rights reserved.