zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

使用EF Core 6执行原始SQL查询

2023-04-18 15:44:06 时间

目录

背景

现有选项

ExecuteSqlRaw

插入

更新

删除

FromSqlRaw

FromSqlInterpolated

自定义数据库上下文扩展方法

ExecuteScalar

ExecuteNonQuery

FromSqlQuery

FromSqlRaw

ExecuteScalar

ExecuteNonQuery

与事务一起使用

与事务范围一起使用

FromSqlQuery

模型

手动映射

使用索引

使用列名

自动映射

FromSqlRaw

使用扩展方法

局限性

引用

关于代码示例


 

背景

实体框架核心允许我们在使用关系数据库时下拉到原始SQL查询。此外,它还提供了使用ADO.NET功能直接对数据库执行原始SQL查询的机制。在这里,我们将探讨在实体框架核心中运行行SQL的现有选项和自定义选项,但将更多地关注使用ADO.NET的扩展方法实现。

现有选项

在实体框架核心中,有多个选项可用于运行原始SQL查询。要使用它们,我们需要安装Microsoft.EntityFrameworkCore.Relational和Microsoft.EntityFrameworkCore:

  1.  
    Install-Package Microsoft.EntityFrameworkCore
  2.  
    Install-Package Microsoft.EntityFrameworkCore.Relational
 

ExecuteSqlRaw

执行非查询 SQL。以下是一些insert、update和delete示例。参数化查询是可选的,如果需要,我们可以跳过它。

插入

  1.  
    object[] paramItems = new object[]
  2.  
    {
  3.  
    new SqlParameter("@paramName", "Ben"),
  4.  
    new SqlParameter("@paramCreatedBy", "Ben"),
  5.  
    new SqlParameter("@paramCreatedOn", DateTime.UtcNow),
  6.  
    new SqlParameter("@paramIsDeleted", true),
  7.  
    };
  8.  
    int items = Db.Database.ExecuteSqlRaw("INSERT INTO Users([Name],
  9.  
    [IsDeleted], CreatedOn, CreatedBy) VALUES (@paramName, @paramIsDeleted,
  10.  
    @paramCreatedOn, @paramCreatedBy)", paramItems);
 

更新

 

  1.  
    object[] paramItems = new object[]
  2.  
    {
  3.  
    new SqlParameter("@paramEmail", "ben@gmail.com"),
  4.  
    new SqlParameter("@paramName", "Ben")
  5.  
    };
  6.  
    int items = Db.Database.ExecuteSqlRaw
  7.  
    ("UPDATE Users SET Email = @paramEmail WHERE [Name] = @paramName", paramItems);
 

删除

 

  1.  
    object[] paramItems = new object[]
  2.  
    {
  3.  
    new SqlParameter("@paramName", "Ben")
  4.  
    };
  5.  
    int items = Db.Database.ExecuteSqlRaw("DELETE FROM Users
  6.  
    WHERE [Name] = @paramName", paramItems);
 

在3.1之前,有ExecuteSqlCommand。

FromSqlRaw<T>

选择数据并映射到现有DbSet<TSource>。

  1.  
    List<User> usersInDb = Db.Users.FromSqlRaw
  2.  
    (
  3.  
    "SELECT * FROM Users WHERE Name=@paramName",
  4.  
    new SqlParameter("@paramName", user.Name)
  5.  
    )
  6.  
    .ToList();
 

这仅适用于DbSet声明。下面Users是一个DbSet<T>,在DbContext中声明。

  1.  
    public class CpuAppDbContext : DbContext
  2.  
    {
  3.  
    public DbSet<User> Users { get; set; }
  4.  
    }
 

FromSqlInterpolated<T>

 

  1.  
    List<User> usersInDb = Db.Users.FromSqlInterpolated<User>
  2.  
    (
  3.  
    $"SELECT * FROM Users WHERE Name={user.Name}"
  4.  
    )
  5.  
    .ToList();
 

自定义数据库上下文扩展方法

下面是一些用于运行原始SQL的扩展方法的DbContext和DatabaseFacade对象。在Database.Core项目的帮助程序类 EfSqlHelper.cs 中,我们将找到列出的扩展方法。

ExecuteScalar

  • 返回查询返回的结果集中第一行的第一列
  • 可选查询参数化
  • 可选命令类型和命令超时

ExecuteNonQuery

  • 执行不返回任何数据的原始SQL查询
  • 返回受影响的行数
  • 可选查询参数化
  • 可选命令类型和命令超时
  • 支持数据库交易

FromSqlQuery<T>

  • 执行返回数据的原始SQL查询
  • Mapp将数据行返回到给定类型T
    • 手动获取Mapp的数据
    • 自动获取Mapp的数据
  • 可选的查询参数化。
  • 可选命令类型和命令超时

FromSqlRaw<T>

  • 内置的通用包装器FromSqlRaw

ExecuteScalar

执行查询,并返回查询返回的结果集中第一行的第一列。其他列或行将被忽略。

  1.  
    using Microsoft.EntityFrameworkCore;
  2.  
    using Microsoft.EntityFrameworkCore.Infrastructure;
  3.  
    using Microsoft.EntityFrameworkCore.Storage;
  4.  
    using System;
  5.  
    using System.Collections.Generic;
  6.  
    using System.Data;
  7.  
    using System.Data.Common;
  8.  
    using System.Linq;
  9.  
    using System.Reflection;
  10.  
     
  11.  
    namespace EfCoreHelper.Database.Core
  12.  
    {
  13.  
    public static class EfSqlHelper
  14.  
    {
  15.  
    public static DbTransaction GetDbTransaction(this IDbContextTransaction source)
  16.  
    {
  17.  
    return (source as IInfrastructure<DbTransaction>).Instance;
  18.  
    }
  19.  
     
  20.  
    public static object ExecuteScalar(this DbContext context, string sql,
  21.  
    List<DbParameter> parameters = null,
  22.  
    CommandType commandType = CommandType.Text,
  23.  
    int? commandTimeOutInSeconds = null)
  24.  
    {
  25.  
    Object value = ExecuteScalar(context.Database, sql, parameters,
  26.  
    commandType, commandTimeOutInSeconds);
  27.  
    return value;
  28.  
    }
  29.  
     
  30.  
    public static object ExecuteScalar(this DatabaseFacade database,
  31.  
    string sql, List<DbParameter> parameters = null,
  32.  
    CommandType commandType = CommandType.Text,
  33.  
    int? commandTimeOutInSeconds = null)
  34.  
    {
  35.  
    Object value;
  36.  
    using (var cmd = database.GetDbConnection().CreateCommand())
  37.  
    {
  38.  
    if (cmd.Connection.State != ConnectionState.Open)
  39.  
    {
  40.  
    cmd.Connection.Open();
  41.  
    }
  42.  
    cmd.CommandText = sql;
  43.  
    cmd.CommandType = commandType;
  44.  
    if (commandTimeOutInSeconds != null)
  45.  
    {
  46.  
    cmd.CommandTimeout = (int)commandTimeOutInSeconds;
  47.  
    }
  48.  
    if (parameters != null)
  49.  
    {
  50.  
    cmd.Parameters.AddRange(parameters.ToArray());
  51.  
    }
  52.  
    value = cmd.ExecuteScalar();
  53.  
    }
  54.  
    return value;
  55.  
    }
  56.  
    }
  57.  
    }
 

在提取方法中,我们使用ADO.NET特征。从Ef DbContext的数据库对象,我们正在访问底层数据库连接对象并从中创建Db命令。然后将所有必需的参数分配给命令对象,如SQL、命令类型、SQL参数、使用现有数据库转换和可选命令超时到新创建的命令。最后,调用ExecuteScalar()以执行原始SQL查询。

  1.  
    int count = (int)Db.ExecuteScalar
  2.  
    (
  3.  
    "SELECT COUNT(1) FROM Users WHERE Name=@paramName",
  4.  
    new List<DbParameter>() { new SqlParameter("@paramName", user.Name) }
  5.  
    );
 

ExecuteNonQuery

对连接执行Transact-SQL语句,并返回受影响的行数。

  1.  
    using Microsoft.EntityFrameworkCore;
  2.  
    using Microsoft.EntityFrameworkCore.Infrastructure;
  3.  
    using Microsoft.EntityFrameworkCore.Storage;
  4.  
    using System;
  5.  
    using System.Collections.Generic;
  6.  
    using System.Data;
  7.  
    using System.Data.Common;
  8.  
    using System.Linq;
  9.  
    using System.Reflection;
  10.  
     
  11.  
    namespace EfCoreHelper.Database.Core
  12.  
    {
  13.  
    public static class EfSqlHelper
  14.  
    {
  15.  
    public static DbTransaction GetDbTransaction(this IDbContextTransaction source)
  16.  
    {
  17.  
    return (source as IInfrastructure<DbTransaction>).Instance;
  18.  
    }
  19.  
     
  20.  
    public static int ExecuteNonQuery(this DbContext context, string command,
  21.  
    List<DbParameter> parameters = null,
  22.  
    CommandType commandType = CommandType.Text,
  23.  
    int? commandTimeOutInSeconds = null)
  24.  
    {
  25.  
    int value = ExecuteNonQuery(context.Database, command,
  26.  
    parameters, commandType, commandTimeOutInSeconds);
  27.  
    return value;
  28.  
    }
  29.  
     
  30.  
    public static int ExecuteNonQuery(this DatabaseFacade database,
  31.  
    string command, List<DbParameter> parameters = null,
  32.  
    CommandType commandType = CommandType.Text,
  33.  
    int? commandTimeOutInSeconds = null)
  34.  
    {
  35.  
    using (var cmd = database.GetDbConnection().CreateCommand())
  36.  
    {
  37.  
    if (cmd.Connection.State != ConnectionState.Open)
  38.  
    {
  39.  
    cmd.Connection.Open();
  40.  
    }
  41.  
    var currentTransaction = database.CurrentTransaction;
  42.  
    if (currentTransaction != null)
  43.  
    {
  44.  
    cmd.Transaction = currentTransaction.GetDbTransaction();
  45.  
    }
  46.  
    cmd.CommandText = command;
  47.  
    cmd.CommandType = commandType;
  48.  
    if (commandTimeOutInSeconds != null)
  49.  
    {
  50.  
    cmd.CommandTimeout = (int)commandTimeOutInSeconds;
  51.  
    }
  52.  
    if (parameters != null)
  53.  
    {
  54.  
    cmd.Parameters.AddRange(parameters.ToArray());
  55.  
    }
  56.  
    return cmd.ExecuteNonQuery();
  57.  
    }
  58.  
    }
  59.  
    }
  60.  
    }
 

提取方法与前一种非常相似。从DbContext的数据库对象中,创建Db命令。然后,将所有必需的参数分配给命令对象,例如SQL、命令类型、SQL参数、使用现有数据库转换以及命令的可选命令超时。最后,调用ExecuteNonQuery()以执行原始SQL查询。

  1.  
    Db.ExecuteNonQuery("DELETE FROM Users WHERE Id < @paramId", new List<DbParameter>()
  2.  
    { new SqlParameter("@paramId", user.Id) });
 

与事务一起使用

 

  1.  
    Exception error = null;
  2.  
    using (var tran = Db.Database.BeginTransaction())
  3.  
    {
  4.  
    try
  5.  
    {
  6.  
    Db.ExecuteNonQuery("UPDATE Users SET Email =
  7.  
    @paramEmail WHERE Id = @paramId", new List<DbParameter>()
  8.  
    { new SqlParameter("@paramEmail", newEmailOfOldUser),
  9.  
    new SqlParameter("@paramId", oldUser.Id) });
  10.  
    Db.ExecuteNonQuery("UPDATE Users SET Email =
  11.  
    @paramEmail WHERE Id = @paramId", new List<DbParameter>()
  12.  
    { new SqlParameter("@paramEmail", newEmailOfUser),
  13.  
    new SqlParameter("@paramId", user.Id) });
  14.  
    tran.Commit();
  15.  
    }
  16.  
    catch (Exception ex)
  17.  
    {
  18.  
    error = ex;
  19.  
    tran.Rollback();
  20.  
    }
  21.  
    }
 

与事务范围一起使用

 

  1.  
    Exception error = null;
  2.  
    using (var scope = new TransactionScope())
  3.  
    {
  4.  
    try
  5.  
    {
  6.  
    Db.ExecuteNonQuery("UPDATE Users SET Email =
  7.  
    @paramEmail WHERE Id = @paramId", new List<DbParameter>()
  8.  
    { new SqlParameter("@paramEmail", newEmailOfOldUser),
  9.  
    new SqlParameter("@paramId", oldUser.Id) });
  10.  
    Db.ExecuteNonQuery("UPDATE Users SET Email = @paramEmail WHERE Id = @paramId",
  11.  
    new List<DbParameter>() { new SqlParameter("@paramEmail", newEmailOfUser),
  12.  
    new SqlParameter("@paramId", user.Id) });
  13.  
    scope.Complete();
  14.  
    }
  15.  
    catch (Exception ex)
  16.  
    {
  17.  
    error = ex;
  18.  
    }
  19.  
    }
 

FromSqlQuery<T>

创建一个原始SQL查询,该查询将返回给定泛型类型的元素。在较旧的实体框架版本中,曾经执行类似操作的是Database.SqlQuery<T>,但在较新版本/核心中被删除。现在,可以通过两种方式完成此泛型类型映射:

  • 手动映射数据
  • 自动映射数据

 

  1.  
    using Microsoft.EntityFrameworkCore;
  2.  
    using Microsoft.EntityFrameworkCore.Infrastructure;
  3.  
    using Microsoft.EntityFrameworkCore.Storage;
  4.  
    using System;
  5.  
    using System.Collections.Generic;
  6.  
    using System.Data;
  7.  
    using System.Data.Common;
  8.  
    using System.Linq;
  9.  
    using System.Reflection;
  10.  
     
  11.  
    namespace EfCoreHelper.Database.Core
  12.  
    {
  13.  
    public static class EfSqlHelper
  14.  
    {
  15.  
    private class PropertyMapp
  16.  
    {
  17.  
    public string Name { get; set; }
  18.  
    public Type Type { get; set; }
  19.  
    public bool IsSame(PropertyMapp mapp)
  20.  
    {
  21.  
    if (mapp == null)
  22.  
    {
  23.  
    return false;
  24.  
    }
  25.  
    bool same = mapp.Name == Name && mapp.Type == Type;
  26.  
    return same;
  27.  
    }
  28.  
    }
  29.  
     
  30.  
    public static DbTransaction GetDbTransaction(this IDbContextTransaction source)
  31.  
    {
  32.  
    return (source as IInfrastructure<DbTransaction>).Instance;
  33.  
    }
  34.  
     
  35.  
    public static IEnumerable<T> FromSqlQuery<T>
  36.  
    (this DbContext context, string query, List<DbParameter> parameters = null,
  37.  
    CommandType commandType = CommandType.Text,
  38.  
    int? commandTimeOutInSeconds = null) where T : new()
  39.  
    {
  40.  
    return FromSqlQuery<T>(context.Database, query, parameters,
  41.  
    commandType, commandTimeOutInSeconds);
  42.  
    }
  43.  
     
  44.  
    public static IEnumerable<T> FromSqlQuery<T>
  45.  
    (this DatabaseFacade database, string query,
  46.  
    List<DbParameter> parameters = null,
  47.  
    CommandType commandType = CommandType.Text,
  48.  
    int? commandTimeOutInSeconds = null) where T : new()
  49.  
    {
  50.  
    const BindingFlags flags = BindingFlags.Public |
  51.  
    BindingFlags.Instance | BindingFlags.NonPublic;
  52.  
    List<PropertyMapp> entityFields = (from PropertyInfo aProp
  53.  
    in typeof(T).GetProperties(flags)
  54.  
    select new PropertyMapp
  55.  
    {
  56.  
    Name = aProp.Name,
  57.  
    Type = Nullable.GetUnderlyingType
  58.  
    (aProp.PropertyType) ?? aProp.PropertyType
  59.  
    }).ToList();
  60.  
    List<PropertyMapp> dbDataReaderFields = new List<PropertyMapp>();
  61.  
    List<PropertyMapp> commonFields = null;
  62.  
     
  63.  
    using (var command = database.GetDbConnection().CreateCommand())
  64.  
    {
  65.  
    if (command.Connection.State != ConnectionState.Open)
  66.  
    {
  67.  
    command.Connection.Open();
  68.  
    }
  69.  
    var currentTransaction = database.CurrentTransaction;
  70.  
    if (currentTransaction != null)
  71.  
    {
  72.  
    command.Transaction = currentTransaction.GetDbTransaction();
  73.  
    }
  74.  
    command.CommandText = query;
  75.  
    command.CommandType = commandType;
  76.  
    if (commandTimeOutInSeconds != null)
  77.  
    {
  78.  
    command.CommandTimeout = (int)commandTimeOutInSeconds;
  79.  
    }
  80.  
    if (parameters != null)
  81.  
    {
  82.  
    command.Parameters.AddRange(parameters.ToArray());
  83.  
    }
  84.  
    using (var result = command.ExecuteReader())
  85.  
    {
  86.  
    while (result.Read())
  87.  
    {
  88.  
    if (commonFields == null)
  89.  
    {
  90.  
    for (int i = 0; i < result.FieldCount; i++)
  91.  
    {
  92.  
    dbDataReaderFields.Add(new PropertyMapp
  93.  
    { Name = result.GetName(i),
  94.  
    Type = result.GetFieldType(i) });
  95.  
    }
  96.  
    commonFields = entityFields.Where
  97.  
    (x => dbDataReaderFields.Any(d =>
  98.  
    d.IsSame(x))).Select(x => x).ToList();
  99.  
    }
  100.  
     
  101.  
    var entity = new T();
  102.  
    foreach (var aField in commonFields)
  103.  
    {
  104.  
    PropertyInfo propertyInfos =
  105.  
    entity.GetType().GetProperty(aField.Name);
  106.  
    var value = (result[aField.Name] == DBNull.Value) ?
  107.  
    null : result[aField.Name]; //if field is nullable
  108.  
    propertyInfos.SetValue(entity, value, null);
  109.  
    }
  110.  
    yield return entity;
  111.  
    }
  112.  
    }
  113.  
    }
  114.  
    }
  115.  
     
  116.  
    public static IEnumerable<T> FromSqlQuery<T>
  117.  
    (this DbContext context, string query, Func<DbDataReader, T> map,
  118.  
    List<DbParameter> parameters = null, CommandType commandType = CommandType.Text,
  119.  
    int? commandTimeOutInSeconds = null)
  120.  
    {
  121.  
    return FromSqlQuery(context.Database, query, map, parameters,
  122.  
    commandType, commandTimeOutInSeconds);
  123.  
    }
  124.  
     
  125.  
    public static IEnumerable<T> FromSqlQuery<T>
  126.  
    (this DatabaseFacade database, string query, Func<DbDataReader, T> map,
  127.  
    List<DbParameter> parameters = null,
  128.  
    CommandType commandType = CommandType.Text,
  129.  
    int? commandTimeOutInSeconds = null)
  130.  
    {
  131.  
    using (var command = database.GetDbConnection().CreateCommand())
  132.  
    {
  133.  
    if (command.Connection.State != ConnectionState.Open)
  134.  
    {
  135.  
    command.Connection.Open();
  136.  
    }
  137.  
    var currentTransaction = database.CurrentTransaction;
  138.  
    if (currentTransaction != null)
  139.  
    {
  140.  
    command.Transaction = currentTransaction.GetDbTransaction();
  141.  
    }
  142.  
    command.CommandText = query;
  143.  
    command.CommandType = commandType;
  144.  
    if (commandTimeOutInSeconds != null)
  145.  
    {
  146.  
    command.CommandTimeout = (int)commandTimeOutInSeconds;
  147.  
    }
  148.  
    if (parameters != null)
  149.  
    {
  150.  
    command.Parameters.AddRange(parameters.ToArray());
  151.  
    }
  152.  
    using (var result = command.ExecuteReader())
  153.  
    {
  154.  
    while (result.Read())
  155.  
    {
  156.  
    yield return map(result);
  157.  
    }
  158.  
    }
  159.  
    }
  160.  
    }
  161.  
    }
  162.  
    }
 

模型

 

  1.  
    public class UserModel
  2.  
    {
  3.  
    public string Name { get; set; }
  4.  
    public string Email { get; set; }
  5.  
    public bool? IsDeleted { get; set; }
  6.  
    }
 

 

  1.  
    DROP TABLE IF EXISTS [dbo].[Users]
  2.  
    GO
  3.  
    CREATE TABLE [dbo].[Users](
  4.  
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
  5.  
    [Name] [nvarchar](max) NULL,
  6.  
    [Email] [nvarchar](max) NULL,
  7.  
    [IsDeleted] [bit] NOT NULL,
  8.  
    [CreatedOn] [datetime2](7) NOT NULL,
  9.  
    [CreatedBy] [nvarchar](max) NOT NULL,
  10.  
    [ModifiedOn] [datetime2](7) NULL,
  11.  
    [ModifiedBy] [nvarchar](max) NULL
  12.  
    )
 

此处Name、Email和IsDeleted都存在于C#模型和Db表中。数据类型也类似。

手动映射

我们可以使用列索引或列名进行手动映射。

使用索引

 

  1.  
    List<UserModel> usersInDb = Db.FromSqlQuery
  2.  
    (
  3.  
    "SELECT Name, Email FROM Users WHERE Name=@paramName",
  4.  
    x => new UserModel
  5.  
    {
  6.  
    Name = (string)x[0],
  7.  
    Email = (string)x[1]
  8.  
    },
  9.  
    new List<DbParameter>() { new SqlParameter("@paramName", user.Name) }
  10.  
    )
  11.  
    .ToList();
 

使用列名

 

  1.  
    List<UserModel> usersInDb = Db.FromSqlQuery
  2.  
    (
  3.  
    "SELECT Name, Email FROM Users WHERE Name=@paramName",
  4.  
    x => new UserModel
  5.  
    {
  6.  
    Name = x["Name"] is DBNull ? "" : (string)x["Name"],
  7.  
    Email = x["Email"] is DBNull ? "" : (string)x["Email"]
  8.  
    },
  9.  
    new List<DbParameter>() { new SqlParameter("@paramName", user.Name) }
  10.  
    )
  11.  
    .ToList();
 

自动映射

映射过程取决于类属性名称、数据类型与列名称以及数据类型。此自动映射是使用反射完成的。因此,最好不要使用此方法选择非常大的数据集。

  1.  
    List<UserModel> usersInDb = Db.FromSqlQuery<UserModel>
  2.  
    (
  3.  
    "SELECT Name, Email, IsDeleted FROM Users WHERE Name=@paramName",
  4.  
    new List<DbParameter>() { new SqlParameter("@paramName", user.Name) }
  5.  
    )
  6.  
    .ToList();
 

FromSqlRaw<T>

这是现有FromSqlRaw<T>的泛型包装器:

  1.  
    using Microsoft.EntityFrameworkCore;
  2.  
    using Microsoft.EntityFrameworkCore.Infrastructure;
  3.  
    using Microsoft.EntityFrameworkCore.Storage;
  4.  
    using System;
  5.  
    using System.Collections.Generic;
  6.  
    using System.Data;
  7.  
    using System.Data.Common;
  8.  
    using System.Linq;
  9.  
    using System.Reflection;
  10.  
     
  11.  
    namespace EfCoreHelper.Database.Core
  12.  
    {
  13.  
    public static class EfSqlHelper
  14.  
    {
  15.  
    public static IQueryable<TSource> FromSqlRaw<TSource>
  16.  
    (this DbContext db, string sql, params object[] parameters)
  17.  
    where TSource : class
  18.  
    {
  19.  
    var item = db.Set<TSource>().FromSqlRaw(sql, parameters);
  20.  
    return item;
  21.  
    }
  22.  
    }
  23.  
    }
 

TSource应包含在作为DbSet<TSource>的DbContext中。

使用扩展方法

 

  1.  
    List<User> usersInDb = Db.FromSqlRaw<User>
  2.  
    (
  3.  
    "SELECT * FROM Users WHERE Name=@paramName",
  4.  
    new SqlParameter("@paramName", user.Name)
  5.  
    )
  6.  
    .ToList();
 

局限性

  • 存储过程未经过测试,但应像EXECsp_name或使用命令类型CommandType.StoredProcedure一样工作
  • FromSqlQuery<T>自动映射是使用反射完成的。可能会面临大型数据集的性能问题。
  • 避免在Linq中加入FromSqlQuery<T>其他的IEnumerable<T>
  • ExecuteNonQuery或FromSqlQuery<T> SQL语句立即执行,无论我们是否调用Db.SaveChanges()
  • ExecuteSqlRaw或者FromSqlRaw<T>,立即执行
  • 使用 SQL Server 和 Oracle 进行测试

引用

关于代码示例

  • Visual Studio 2022 Solution
  • ASP.NET 6
  • EF Core 6
  • 此示例也在Core 5中进行了测试

Database.Test 是一个有趣的单元测试项目。在appsettings.json中更改连接字符串。在db中创建用户表,检查项目 Database.Application 的db.sql。检查/运行EfSqlHelperTests.cs的单元测试

  1.  
    {
  2.  
    "ConnectionStrings": {
  3.  
    "DatabaseConnection": "Data Source=.\SQLEXPRESS;Initial Catalog=Cup;Integrated Security=True"
  4.  
    }
  5.  
    }

 

 

  1.  
    DROP TABLE IF EXISTS [dbo].[Users]
  2.  
    GO
  3.  
    CREATE TABLE [dbo].[Users](
  4.  
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
  5.  
    [Name] [nvarchar](max) NULL,
  6.  
    [Email] [nvarchar](max) NULL,
  7.  
    [IsDeleted] [bit] NOT NULL,
  8.  
    [CreatedOn] [datetime2](7) NOT NULL,
  9.  
    [CreatedBy] [nvarchar](max) NOT NULL,
  10.  
    [ModifiedOn] [datetime2](7) NULL,
  11.  
    [ModifiedBy] [nvarchar](max) NULL
  12.  
    )

 

https://www.codeproject.com/Articles/5321286/Executing-Raw-SQL-Queries-using-Entity-Framework-C

 

转 https://blog.csdn.net/mzl87/article/details/128646754