如何使用EF Core进行原始SQL插入查询并返回行?

3

我使用EF Core for PostgreSQL,如此处所述。我想执行一些返回行的原始SQL查询。

最简单的一个是这个(它看起来很奇怪,因为它返回插入的内容,但它很简单,可以用作示例):

INSERT INTO public."TodoItems" ("Id", "Todo") VALUES ('915714b6-1c67-444d-8106-d778fcb4bb1a', 'Hi') RETURNING "Id", "Todo"

这是我的上下文类:

public class DoContext : DbContext
{
    public DoContext(DbContextOptions<DoContext> options) : base(options)
    {
        Console.WriteLine("Context created");
    }

    public DbSet<TodoItem> TodoItems { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        Console.WriteLine("OnModelCreating");
    }
}

这是实体类。

public class TodoItem
{
    public Guid Id { get; set; }

    public string Todo { get; set; }
}

这是执行查询的代码:

string query = "INSERT INTO public.\"TodoItems\" (\"Id\", \"Todo\") VALUES ('915714b6-1c67-444d-8106-d778fcb4bb1a', 'Hi') RETURNING \"Id\", \"Todo\"";
var result = context.TodoItems.FromSqlRaw(query).First();

我的查询是没问题的。当表为空且在DataGrip中执行查询时,它可以正常工作。但是,在运行我的代码时,最后一行会导致以下异常:

Npgsql.PostgresException 42601: "INTO" 附近的语法错误

从文档中我了解到,当需要返回行时,FromSqlRaw 是正确的方法。然而,这种方法似乎无法理解我的(经过测试和验证的)查询。

那么,我该如何使用 EF Core 执行此查询呢?重要的是,我真的需要使用 EF Core,因为我需要将 SQL 世界和实体之间进行映射。我使用 .NET 5。
1个回答

4
避免使用像First等查询限制运算符,因为EF Core将尝试在提供的SQL上进行组合 - 基本上是将其包装在外部SELECTSELECT * FROM(Your_SQL))中以应用TOP N或类似运算符。这会导致无效的SQL语法。

因此,使用材料化运算符而不是查询限制运算符 - ToList()ToArray()AsEnumerable()来停止IQueryable处理并在那一点上执行数据库查询,例如:

var result = context.TodoItems.FromSqlRaw(query)
    .AsEnumerable() // <-- database query ends here
    .First(); // <-- this runs in LINQ to Objects context

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接