【发布时间】:2020-03-05 12:34:40
【问题描述】:
我有一个包含 40 个表的 Sql DB,我构建了代表每个表的模型,我还使用 Dapper 作为我的 ORM...
我正在 DAL(数据访问层)中构建我的 CRUD 语句,它将采用 myModelObj(通过 HTTPPost 进入)和 modelName(通过 URL 参数进入)
我还有一个方法 (MyMapper) 可以将我的 myModelObj 映射到我的模型 - 但是我创建的方法是 object 类型,它返回 System.Object 类型 - 我希望发生的事情是方法返回模型并动态/在运行时转换调用方法的数据类型,以匹配返回的模型类型...
我的代码:
控制器
private readonly IDbOperation _dbo;
...
...
public DataController(IDbOperation dboperation)
{
_dbo = dboperation;
}
...
[HttpPost("create/{modelName}", Name = "Generic CRUD: Create Method")]
[Produces("application/json")]
public ActionResult Create([FromBody] JObject createObject, string modelName)
{
try
{
... ... ...
object response = _dbo.CreateRecord(createObject, modelName);
// HTTP Post Body example
{
"Fullname": "Juan Carlos",
"Firstname": "Juan",
"Lastname": "Carlos",
"Salutation": "Dr.",
"Age": 30,
"CreatedOn": "2019-11-07T12:25:10"
}
数据库操作
private readonly IDbConnector _dbConnector
...
public DbOperation(IDbConnector dbConnector)
{
_dbConnector = dbConnector;
}
public JsonResult CreateRecord(JObject model, string modelName)
{
... ... ...
var create = MyMapper(modelName, model); // <<<
... ...
try
{
using (var connection = _dbConnector.GetMsSqlConnection())
{
// https://dapper-tutorial.net/insert
var createdId = connection.Insert(create);
...
}
}
}
private object MyMapper(string modelName, JObject mod)
{
switch (modelName.ToLower())
{
case "transaction":
return JsonConvert.DeserializeObject<ModelRepoDTO.Transaction>(model.ToString());
case "items":
return JsonConvert.DeserializeObject<ModelRepoDTO.Items>(model.ToString());
case "users":
return JsonConvert.DeserializeObject<ModelRepoDTO.Users>(mod.ToString());
...
...
default:
_logger.Error("DataAccessLayer", "DbOperation", ">>> Mapping decision could not be made");
break;
}
}
数据库连接器
public class DbConnector : IDbConnector
{
private readonly string _connectionstring;
public DbConnector(IConfiguration config)
{
_connectionstring = config.GetValue<string>("Connectionstring");
}
public SqlConnection GetMsSqlConnection()
{
SqlConnection conn = null;
try
{
conn = new SqlConnection(_connectionstring);
conn.Open();
if (conn.State != ConnectionState.Open)
{
// throw error
}
}
catch (Exception ex)
{
if (conn != null && conn.State == ConnectionState.Open)
{
conn.Close();
}
conn = null;
}
// return the connection
return conn;
}
}
(当前)从MyMapper("User", {<Object from HTTP Post>}) 返回的数据类型是System.Object,因为MyMapper 的类型是object
我想要的是动态更改数据类型以匹配模型...
MyMapper("User", {<Object from HTTP Post>}) => 数据类型 = User
请记住,我可以针对 40 个不同的表/模型进行 CRUD 处理,显然在运行时之前我不会知道调用了哪个表/模型...
(完成示例)
...我把从MyMapper 返回的对象传递给connection.insert(...);
(我修改了我的帖子以显示这一点 - 看看 DbOperation)
有什么建议吗?想法?
【问题讨论】:
-
MyMapper的通用方法可能是最优雅的解决方案...在某些时候,您需要明确指定您期望的类型,所以您不会例如,能够输入一个 JSON 字符串并在没有某种映射的情况下神奇地获得预期的类型(可能由一个巨大的switch语句实现) -
有趣的是你提到...
MyMapper是一个巨大的switch声明...我将更新我的帖子,其中一些只是为了说明 -
明智的设计,感觉就像你试图让一个方法处理许多不同的类型,但就像
object。总之——从长远来看,这将是痛苦的。要么更改映射器以返回泛型,要么(我建议)制作 40 种不同的操作方法(端点)。当然,会有一些代码重复,但很容易阅读和推理。 -
@user1538301 如果需要,OP 甚至可以保留其现有的 URL 结构。将
create/bob路由到一个操作,create/cathy到另一个操作等等。 -
更改
MyMapper以使用泛型 - 因此它将采用T类型而不是string模型名称。当您尝试这样做时,您将意识到“40 个不同端点”方法的好处(因为您需要能够在编译时传入泛型类型)。是的,这将是一些工作。 :)
标签: c# asp.net-core