首页 > 解决方案 > 使用 INNER JOIN 将 SQL 查询转换为实体 SQL 查询 - C#

问题描述

我动态构建以下 SQL 查询:

StringBuilder query = new StringBuilder();
StringBuilder query2 = new StringBuilder();

if (ComboRuleType.Text.Equals("Standard"))
{
    query.Append("select * from [dbo].[" + ComboRuleTableName.Text + "]" + " WHERE" + "\n");
    query.Append("(" + "\n");

    for (int i = 0; i < dgvUpdateCriteria.RowCount; i++)
    {
        DataGridViewRow row = dgvUpdateCriteria.Rows[i];

        if (i != 0)
        {
            query.Append(row.Cells[1].Value.ToString() + " " + row.Cells[3].Value.ToString() + " ");
        }
        else
        {
            query.Append(row.Cells[3].Value.ToString() + " ");
        }

        if (row.Cells[4].Value.ToString().Equals("Contains"))
        {
            query.Append("like " + "'%" + row.Cells[5].Value.ToString() + "%'" + "\n");
        }
        else if (row.Cells[4].Value.ToString().Equals("Equals"))
        {
            query.Append("= " + "'" + row.Cells[5].Value.ToString() + "'" + "\n");
        }
        else if (row.Cells[4].Value.ToString().Equals("StartsWith"))
        {
            query.Append("like " + "'" + row.Cells[5].Value.ToString() + "%'" + "\n");
        }
        else if (row.Cells[4].Value.ToString().Equals("EndsWith"))
        {
            query.Append("like " + "'%" + row.Cells[5].Value.ToString() + "'" + "\n");
        }
    }

    query.Append(")" + "\n");
    return query.ToString();
}

将上述转换为 Entity SQL 后,它看起来像:

StringBuilder query = new StringBuilder();
StringBuilder query2 = new StringBuilder();

if (ComboRuleType.Text.Equals("Standard"))
{
    query.Append("select value q1 from ");
    query.Append(ComboRuleTableName.Text);
    query.Append("s");
    query.Append(" as q1 where " + "\n");
    for (int i = 0; i < dgvUpdateCriteria.RowCount; i++)
    {
        DataGridViewRow row = dgvUpdateCriteria.Rows[i];

        if (i != 0)
        {
            if (row.Cells[1].Value.ToString().Equals("AND"))
            {
                query.Append("&&" + " " + "q1." + row.Cells[3].Value.ToString());
            }
            else
            {
                query.Append("||" + " " + "q1." + row.Cells[3].Value.ToString());
            }
        }
        else
        {
            query.Append("q1." + row.Cells[3].Value.ToString());
        }

        if (row.Cells[4].Value.ToString().Equals("Contains"))
        {
            query.Append(" LIKE (" + "'%" + row.Cells[5].Value.ToString() + "%'" + ")" + "\n");
        }
        else if (row.Cells[4].Value.ToString().Equals("Equals"))
        {
            query.Append(" == (" + "'" + row.Cells[5].Value.ToString() + "'" + ")" + "\n");
        }
        else if (row.Cells[4].Value.ToString().Equals("StartsWith"))
        {
            query.Append(" LIKE (" + "'" + row.Cells[5].Value.ToString() + "%'" + ")" + "\n");
        }
        else if (row.Cells[4].Value.ToString().Equals("EndsWith"))
        {
            query.Append(" LIKE (" + "'%" + row.Cells[5].Value.ToString() + "'" + ")" + "\n");
        }
    }

    return query.ToString();
}

我构建了另一个 SQL 查询,其中包含INNER JOIN并且我到处查看,但找不到该 SQL 查询到实体 SQL 查询的等效转换。如果您能帮助我,我将不胜感激。动态SQL查询INNER JOIN如下:

query.Append("SELECT * ");
query.Append("FROM [dbo].[membership] mm \n");
query.Append("INNER JOIN [dbo].[" + ComboRuleTableName.Text + "] xx \n");
query.Append("ON (mm.m_" + ComboRuleTableName.Text + "_id = xx.id) \n");
query.Append("WHERE xx.id IN ( \n");
query.Append("SELECT id from [dbo].[" + ComboRuleTableName.Text + "] \n");
query.Append("WHERE \n");
query.Append("mm.platform_name = '" + ComboRulePlatformName.Text + "' AND (\n");

for (int i = 0; i < dgvUpdateCriteria.RowCount; i++)
{
    DataGridViewRow row = dgvUpdateCriteria.Rows[i];
    if (i != 0)
    {
        query2.Append(row.Cells[1].Value.ToString() + " " + row.Cells[3].Value.ToString() + " ");
    }
    else
    {
        query2.Append(row.Cells[3].Value.ToString() + " ");
    }

    if (row.Cells[4].Value.ToString().Equals("Contains"))
    {
        query2.Append("like " + "'%" + row.Cells[5].Value.ToString() + "%'" + "\n");
    }
    else if (row.Cells[4].Value.ToString().Equals("Equals"))
    {
        query2.Append("= " + "'" + row.Cells[5].Value.ToString() + "'" + "\n");
    }
    else if (row.Cells[4].Value.ToString().Equals("StartsWith"))
    {
        query2.Append("like " + "'" + row.Cells[5].Value.ToString() + "%'" + "\n");
    }
    else if (row.Cells[4].Value.ToString().Equals("EndsWith"))
    {
        query2.Append("like " + "'%" + row.Cells[5].Value.ToString() + "'" + "\n");
    }
    else
    {
        query2.Append(" \n");
    }
}

query2.Append("))\n");
return query.Append(query2).ToString();

我需要它是字符串格式。我后来将它从字符串转换为查询格式。我只是不知道INNER JOIN语法如何与实体查询一起使用。

谢谢你。

编辑1:

这是我将该查询转换为实体框架对象查询的方法:

                string query = EntityPreview(); //EntityPreview() is the method that gives me Raw Entity SQL Query
                var objctx = (context as IObjectContextAdapter).ObjectContext;
                if (ComboRuleTableName.Text.Equals("system"))
                {
                    ObjectQuery<system> standardList = objctx.CreateQuery<system>(query);
                    rulePreviewForm.dataGridViewCriteriaRulePreview.DataSource = standardList;
                    rulePreviewForm.Show();
                }

标签: c#sqlentity-frameworkentity-sql

解决方案


EntityFramework 最伟大的事情之一是它为您构建 SQL 并允许您操作对象而不是 SQL。如果您有选择的话,还有其他库(例如 Dapper)在使用直接 SQL 时会更快。如果你必须使用EntityFramework,你最好写Linq。

当使用 Linq 而不是 SQL 时,您仍然可以使用 IQueryable 构建动态查询。这使您无需预先从数据库中提取任何数据即可构建查询。

在不了解您尝试对您的应用程序做什么的情况下,我只能提供一些尝试的提示。在下面的答案中,我对如何设置实体的命名做出了一些假设。

要从成员资格表中获取成员资格列表,假设该表的实体称为 Membership:

IQueryable<Membership> memberships = context.Memberships;

那是你的

query.Append("SELECT * ");
query.Append("FROM [dbo].[membership] mm \n");

对于您的过滤器,您可能希望将它们放入列表中。

从这一点开始,动态部分就派上用场了。如果您有一个名为 [ComboRuleTable1] 的 ComboRule 表和另一个名为 [ComboRuleTable2] 的表,但您必须根据来自 ComboRuleTableName.Text 的输入进行查询,您可以做一些事情像这样。

var filters = new List<string>() { "name1", "name2" };

// Get which table you should join to
switch (ComboRuleTable1)
{
   // Join to tables and get filtered data
   case "ComboRuleTable1":
      memberships = memberships.ComboRuleTable1.Where(x => filters.Contains(x.PlatFormName));
      break;
   case "ComboRuleTable2":
      memberships = memberships.ComboRuleTable2.Where(x => filters.Contains(x.PlatFormName));
      break;
   default:
      break;
}

// This pulls the data from the database
var result = memberships.ToList();

其中一些会因您的 EntityFramework 的设置方式而异。

我希望这有帮助。


推荐阅读