C#.Net Core利用DbSet <tentity> .FromSql

时间:2018-06-28 19:04:45

标签: c# generics asp.net-core asp.net-core-2.0

我们有一组控制器,这些控制器返回JSON数据以通过Web API同步实体。每个数据实体都有自己的控制器和数据模型(“订单,项目,客户...”) 因此,这实际上使每个控制器都使用完全相同的代码。唯一的区别是控制器/ Web api路径的名称,以及将通过JSON返回的数据模型。 我们想要做的是拥有一个所有其他控制器都实现/扩展的基本控制器(BaseController.cs)。为此,我们希望每个子控制器类定义的基类中都有一个虚拟的“ EntityType”或“ EntityName”属性。然后,不必在每个控制器中重复执行返回数据的代码。 我们的问题是我们无法弄清楚如何存储/传递/定义“类型”或“ TEntity”变量。并且我们需要执行此命令来执行“ Get” api方法的主要部分:

示例:

var returnValue = dbContext.Set<GetEntityModelClass()>().FromSql("EXEC dbo.[AJ_P_{0}_API]", GetEntityModelName()).ToList();

我们像这样在BaseController.cs类中实现GetEntityModelName():

public virtual string GetEntityName() { return null; }

和子控制器类的示例将具有以下内容:

public override string GetEntityName() { return "Product"; }

对于可传递dbContext.Set()调用所需值的可比较GetEntityModelClass(),我们该怎么做?

如果有帮助,这里是我们的代码的更大示例:

BaseController.cs
-----------------------------------------
namespace API.Controllers
{
    [Produces("application/json")]
    public class BaseController : Controller
    {

        // Returns the name of an entity as it is used in stored procedures, class names, etc...
        public virtual string GetEntityName()
        {
            return null;
        }
        // Return a type that can be utilized with the dbContext.Set<???>() call
        public virtual ??? GetEntityName()
        {
            return ???;
        }
        // SiteContext is the API site's data context.
        protected readonly SiteContext dbContext;
        public BaseController(SiteContext context)
        {
            dbContext = context;
        }

        [HttpGet("{token}")]
        public IActionResult Get([FromRoute] string token)
        {
            return Get(token);
        }
        public IActionResult Results(string token)
        { 
            if (!ModelState.IsValid) { return BadRequest(ModelState); }

            var returnValue = dbContext.Set<???GetEntityModel()???>().FromSql("EXEC dbo.[AJ_P_{0}_API] @Token={1}", GetEntityName(), token).ToList();

            return Ok(returnValue);
        }
    }
}

ProductController.cs
-----------------------------------------

namespace API.Controllers
{
    [Produces("application/json")]
    [Route("/Product")]
    public class ProductController : BaseController
    {
        public override string GetEntityName() {
            return "Product";
        }
        public override ???? GetEntityModel() {
            return ( ??? ProductModel type ??? )
        }

        public ProductController(SiteContext context) : base(context) { }

    }
}

1 个答案:

答案 0 :(得分:3)

我不喜欢通用基本控制器。但是,您可以使控制器通用,将所需的实体类型作为类型参数。应该可以解决您的问题。

使用样品控制器

[Produces("application/json")]
public abstract class BaseController<TEntity, TModel> : Controller
    where TEntity : class 
    where TModel : class {

    // Returns the name of an entity as it is used in stored procedures, class names, etc...
    protected virtual string GetEntityName() {
        return typeof(TEntity).Name;
    }

    // SiteContext is the API site's data context.
    protected readonly SiteContext dbContext;
    protected BaseController(SiteContext context) {
        dbContext = context;
    }

    [HttpGet("{token}")]
    public IActionResult Get([FromRoute] string token) {
        return GetInternal(token);
    }

    protected abstract TModel Map(TEntity entity);

    protected virtual IActionResult GetInternal(string token)  
        if (!ModelState.IsValid) { return BadRequest(ModelState); }
        var sql = string.Format("EXEC dbo.[AJ_P_{0}_API] @Token", GetEntityName());
        var entities = dbContext.Set<TEntity>().FromSql(sql, token).ToList();
        var returnValue = entities.Select(Map);
        return Ok(returnValue);
    }
}

然后,派生的控制器将只提供type参数。

[Produces("application/json")]
[Route("[controller]")]
public class ProductController : BaseController<Product, ProductModel> {

    public ProductController(SiteContext context) : base(context) { }

    protected override ProductModel Map(Product entity) {
        return new ProductModel {
            Property1 = entity.Property1,
            //...
            PropertyN = entity.PropertyN,
        }
    }
}