在 Lambda 查询中从不同表中选择

问题描述 投票:0回答:2

我需要从不同的表中选择数据。我不想为每个表重复一次相同的代码。有解决办法吗? 以前,表名可以在 SQL 命令中指定为变量。就安全性而言有点危险,但我需要这个东西。

如果不可能,如何直接在 ASP.NET Core 中运行 SQL 命令

string tblname="users";

select * from {tblname};

从不同表中选择数据或直接在 ASP.NET Core 中运行 SQL 命令

在此代码中,我希望博客名称是可变的

var retdata= context.blogs.FromSql("SELECT * From Blogs").ToList();
asp.net-core lambda
2个回答
0
投票

可以用字典或者数据表来实现。

  1. 在您的 dbcontext 文件中
public class LinqTest2Context : DbContext
{
    public LinqTest2Context (DbContextOptions<LinqTest2Context> options)
        : base(options)
    {
    }

    public DbSet<LinqTest2.Models.User> User { get; set; } = default!;
    public DbSet<LinqTest2.Models.Inf> Inf { get; set; } = default!;

    public List<Dictionary<string, object>> GetJoinedTableDataAsList(
        string tableA, string tableB,
        string tableAColumn, string tableBColumn,
        IEnumerable<string> columnNames)
    {
        // Validate the table and column name to prevent SQL injection
        var tableNames = this.Model.GetEntityTypes().Select(t => t.GetTableName()).ToList();
        if (!tableNames.Contains(tableA) || !tableNames.Contains(tableB))
        {
            throw new ArgumentException("Invalid table name.");
        }

        var allowedColumnNamesA = this.Model.GetEntityTypes()
            .FirstOrDefault(t => t.GetTableName() == tableA)?
            .GetProperties().Select(p => p.GetColumnName()).ToList();

        var allowedColumnNamesB = this.Model.GetEntityTypes()
            .FirstOrDefault(t => t.GetTableName() == tableB)?
            .GetProperties().Select(p => p.GetColumnName()).ToList();

        var selectedColumns = columnNames.Where(c => allowedColumnNamesA.Contains(c) || allowedColumnNamesB.Contains(c)).ToList();
        if (!selectedColumns.Any())
        {
            throw new ArgumentException("Invalid or no column names provided.");
        }

        //Verify column names of table
        var columnList = string.Join(", ", selectedColumns.Select(c => $"{(allowedColumnNamesA.Contains(c) ? "A" : "B")}.[{c}]"));
        var resultList = new List<Dictionary<string, object>>();
        var sql = $"SELECT {columnList} FROM [{tableA}] A JOIN [{tableB}] B ON A.[{tableAColumn}] = B.[{tableBColumn}]";

        var command = Database.GetDbConnection().CreateCommand();
        command.CommandText = sql;
        Database.OpenConnection();

        var reader = command.ExecuteReader();
        var dataTable = new DataTable();
        dataTable.Load(reader);
        resultList = dataTable.AsEnumerable().Select(row =>
        {
            var dict = new Dictionary<string, object>();
            foreach (DataColumn col in dataTable.Columns)
            {
                dict[col.ColumnName] = row[col];
            }
            return dict;
        }).ToList();

        return resultList;
    }
}
  1. 在你的方法中可以这样调用
var tableA = "User";
var tableB = "Inf";
var tableAColumn = "InfId";
var tableBColumn = "InfNum";
var columns = new List<string> { "InfName", "UserName" };
var data = _context.GetJoinedTableDataAsList(tableA, tableB, tableAColumn, tableBColumn, columns);


0
投票

1。选项一: 您可以使用带参数的存储过程

@tableName

CREATE PROCEDURE usp_DataFromTable
    @TableName NVARCHAR(255)
AS
BEGIN
    DECLARE @SqlQuery NVARCHAR(MAX);
    SET @SqlQuery = 'SELECT * FROM ' + QUOTENAME(@TableName);
    EXEC sp_executesql @SqlQuery;
END

在 ASP.NET Core 中,您可以使用 Entity Framework Core 调用此存储过程:

string tableName = "users";
var retdata = context.Database.SqlQuery<MyEntity>("usp_DataFromTable @p0", tableName).ToList();

2。选项二: 通过使用

FromSqlRaw
方法,直接在 ASP.NET Core 中使用动态 SQL。

string tableName = "users";
string sqlQuery = $"SELECT * FROM {tableName}";
var data = context.MyEntities.FromSqlRaw(sqlQuery}").ToList();
© www.soinside.com 2019 - 2024. All rights reserved.