gpt4 book ai didi

c# - 如何使用 ValueConversions 检索 Entity Framework Core 的数据库模型

转载 作者:行者123 更新时间:2023-11-30 22:53:11 24 4
gpt4 key购买 nike

我有一个 asp.net 核心 web api 项目,我在其中使用 Entity Framework 。我从 Web 获取 DTO 并将其转换(使用 AutoMapper)为数据库实体。

此时,我可以在实体到达数据库之前在服务器上对其进行一些后处理。由于 Entity Framework 中的数据库结构和限制,我需要将此实体传递给存储过程。此时我想获得应用了转换的数据库模型。

基本上,这个流程...

Controller 接受 DTO -> AutoMapper to Entity -> 允许我在保存之前处理对象和做事 -> 保存,但使用存储过程。

我的模型有一个转换,那么我如何在执行查询时获得我想要的数据库表示?

问题是我在 Controller 中得到“false”作为参数,在实体模型中它被转换为 bool 值,当我想保存它时它被转换为字符串(“false”),我该如何应用 Entity Framework 模型中定义的转换,以便我可以按预期保存“Y”或“N”?

下面的简化示例...

为了澄清这个问题,我需要能够在调用存储过程之前获取模型的数据库表示,使用下面的代码,将调用 ToString,因此我将得到“false”而不是“N” .在使用 ValueConversions(即数据库 -> 模型)检索数据时,我有一种方法可以做到这一点。如果我使用 SaveChanges,EF Core 会负责转换(模型 -> 数据库),但是当使用原始 SQL(在存储过程的情况下)时,我如何获取数据库表示。在这一点上,如果我的模型有一个 bool 属性,我想将“Y”或“N”作为参数传递给原始 SQL……这样更清楚吗?

public class TodoDto
{
[ReadOnly(true)]
public long Id{ get; set; }

public string Item { get; set; }

public bool Done { get; set; }

public DateTime? DateStamp { get; set; }
// other properties, model is more complex, but removed to keep it simple
}

public class TodoEFCoreModel
{
[Column("TodoId"), ReadOnly(true)]
public long Id { get; set; }

[Column("TodoItem")]
public string Item { get; set; }

public bool? Done { get; set; }

public DateTime? DateStamp { get; set; }
// other properties
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var yesNoConversion = new YesNoToBoolConverter();

modelBuilder
.Entity<TodoEFCoreModel>()
.Property(x => x.Done)
.HasConversion(yesNoConversion);
}

public ActionResult PostToDo(TodoDto todo)
{
// code is then roughly
var databaseTodoEntity = _mapper.Map<TodoDto, TodoEFCoreModel>(todo);

// here I can check databaseTodoEntity boolean property
// and/or manipulate the model

// when it comes to saving I need to use a stored procedure, I can do this using ExecuteSqlCommandAsync...
await _dbContext.Database.ExecuteSqlCommandAsync("begin CreateTodo(Item => :p0, Done => :p1, DateStamp => :p2); end;", parameters: new[]
{
new OracleParameter("p0", OracleDbType.VarChar2, databaseTodoEntity.Item, ParameterDirection.Input),

// The problem is here, with this code I get "false", instead of the conversion that Entity Framework would apply if I were to be able to call "SaveChanges" on the db context...
new OracleParameter("p1", OracleDbType.Varchar2, databaseTodoEntity.Done, ParameterDirection.Input),

new OracleParameter("p2", OracleDbType.Date, databaseTodoEntity.DateStamp, ParameterDirection.Input)
});
}

最佳答案

EF Core 内部使用 RelationalTypeMapping类实例,它

Represents the mapping between a .NET type and a database type.

对于特定的实体属性可以通过FindRelationalMapping获得扩展方法。

请注意,此方法被视为“内部”API 的一部分,因此您需要

using Microsoft.EntityFrameworkCore.Internal;

接受典型的警告

This API supports the Entity Framework Core infrastructure and is not intended to be used directly from your code. This API may change or be removed in future releases.

现在,连同 Converter和其他有用的属性,您还可以访问一些有用的方法,例如 CreateParameter ,可以直接在您的场景中使用。与 EF Core 生成的命令一样,它将执行所有必要的转换和参数准备。

例如:

var sql = "begin CreateTodo(Item => :p0, Done => :p1, DateStamp => :p2); end;";
var entityType = _dbContext.Model.FindEntityType(typeof(TodoEFCoreModel));
var dbCommand = _dbContext.Database.GetDbConnection().CreateCommand();
object[] parameters =
{
entityType.FindProperty("Item").FindRelationalMapping()
.CreateParameter(dbCommand, "p0", databaseTodoEntity.Item),
entityType.FindProperty("Done").FindRelationalMapping()
.CreateParameter(dbCommand, "p1", databaseTodoEntity.Done),
entityType.FindProperty("DateStamp").FindRelationalMapping()
.CreateParameter(dbCommand, "p2", databaseTodoEntity.DateStamp),
};
await _dbContext.Database.ExecuteSqlCommandAsync(sql, parameters);

请注意,DbCommand 实例仅用作 DbParameter 工厂 (DbCommand.CreateParameter)。创建的参数不会添加到该命令,因此之后可以安全地丢弃它。

关于c# - 如何使用 ValueConversions 检索 Entity Framework Core 的数据库模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57510185/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com