【问题标题】:How would I get a filtered result from 2 joined tables in a model如何从模型中的 2 个连接表中获得过滤结果
【发布时间】:2019-12-16 18:15:52
【问题描述】:

我有两个用外键链接的 SQL 表。我想在 ASP.NET Core MVC 中的模型中将子表中的值过滤(在哪里)的这个连接的结果。我该怎么做。

我在 SQL 中有这 2 个带有外键的表。我先做了一个数据库。所以,我的项目中有模型。

此外,我还为这些模型创建了接口。

假设表 1 是 Order,表 2 是 OrderLine。 在 SQL 级别上,我会执行以下操作:

SELECT 
  Order.CustomerName
  , OrderLine.Product 
FROM Order 
JOIN OrderLine 
  ON Order.OrderID = OrderLine.OrderID 
WHERE OrderLine.NotYetDelivered = True

因此,我想查看包含他们订购但尚未收到的产品的客户列表。

如何在 ASP.NET Core 中使用 MVC 执行此操作?

我在 Linq 上做了很多尝试。并有以下代码:

var classification = classificationRepository.getAllClassifications();
var classificationLanguage = classificationLanguageRepository.getAllClassificationLanguages();

var ClassificationOne1Language = (from c in classification
                                         join l in classificationLanguage
                                           on c.SuClassificationId equals l.SuClassificationId
                                         //where l.SuLanguageId == 1
                                         select new { c.SuClassificationId, l.SuClassificationName });
        //var ClassificationOne1Language = (from c in classificationLanguage
        //                                 select new { c.SuClassificationId, c.SuClassificationName });

        List<ClassificationWithLanguageViewModel> x = new List<ClassificationWithLanguageViewModel>();
        foreach (var c in ClassificationOne1Language)

它在“foreach”循环中显示以下内容: System.Data.SqlTypes.SqlNullValueException:'数据为空。不能对 Null 值调用此方法或属性。'

但是当我使用 SQL 探查器时,我得到以下 SQL 并且有 2 行结果。

SELECT [s].[SuClassificationID], [s].[SuClassificationColor], [s].[SuClassificationStatusID], [s].[SuCreateDate], [s].[SuCreatorID], [s].[SuDefaultClassficiationPageID], [s].[SuDropDownSequence], [s].[SuHasDropDown], [s].[SuModifierID], [s].[SuModifyDate]
FROM [SuClassification] AS [s]

任何建议为什么在 SQL 级别上我有结果但代码认为不同?

【问题讨论】:

  • 我建议研究实体框架核心。然后,您可以在 SQL 代码中使用 Linq 查询来查询表并将值分配给您的模型。
  • 为了清楚起见,有许多不同的方法可以满足您的要求。您可能应该只搜索“asp.net 从数据库中检索数据”,找到看起来像您需要的东西并尝试一下,然后在遇到问题时提出问题。
  • 谢谢。我确实尝试过类似的东西(我尝试了很多东西)。如果我创建一个视图模型并根据 linq 查询填充它。这会是一条路吗?
  • 仅供参考。它实际上与订单无关,但这样更容易解释。我自愿为社区建立一个分享可持续发展知识的平台。
  • 是的,这样就可以了。

标签: c# asp.net-mvc asp.net-core model-view-controller model


【解决方案1】:

如果您从多个表中获取结果并创建一个实体,那么下面的代码可以帮助您。

您的要求是使用 join 执行查询并获取结果。

首先创建与您的查询返回结果相关的模型。例如

public class Result
{
     public string CustomerName { get; set; }
     public string Product { get; set; }
}

现在在 DbContext OnModelCreating() 方法中将此模型绑定到您的查询

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
      modelBuilder.Query<Result>();
}

现在您可以使用自定义模型访问和执行您的查询。

 var query = @"SELECT 
                     Order.CustomerName, 
                     OrderLine.Product 
               FROM Order 
               JOIN OrderLine 
               ON Order.OrderID = OrderLine.OrderID 
               WHERE OrderLine.NotYetDelivered = True";
 var results = _dbContext.Query<Result>().FromSql(query).ToList(); 

你也可以像下面这样传递参数

var idParam= new System.Data.SqlClient.SqlParameter("@id", id);
var results = _dbContext.Query<Result>().FromSql(query,idParam).ToList(); 

并在查询中使用@id 作为参数。

通过这种方式,您可以访问或设置您的自定义模型并在实体框架核心中执行查询。

如果你使用 Linq 访问,]

var orderLines = _context.OrderLines.Include(x => x.Order)
                         .Where(ol => ol.NotYetDelivered)
                         .Select(ol => new
                         {
                               CustomerName = ol.Order.CustomerName,
                               Product = ol.Product
                         }).ToList();

这里Include方法指定要包含在查询结果中的相关数据。

让我知道需要更多信息。

【讨论】:

  • 嗨 Lalji,我会试一试。不过会带我一点。在 Linq 上苦苦挣扎。
  • @PeterleGrand 只是将查询模型作为您的查询结果,其他事情相同,或者您可以执行返回选择与执行 sql 查询相同的方式的存储过程
  • 不明白最后的评论。查询模型是什么意思?我喜欢您在常规 SQL 中执行此操作的想法,因为我对此更熟悉。我只看到人们在做 Linq 的原因是什么?那是因为你让它独立于数据库系统吗?或任何其他原因?我想用正确的技术做这个项目,所以如果有任何理由不按照你的建议用 SQL 做,我会继续学习。但是,如果您对常规 SQL 的想法与您的想法一样好,我可能会先这样做,因为我觉得 SQL 比 Linq 更熟悉。
  • @PeterleGrand 查询模型?表示返回您的查询结果的Result。看到使用 linq 就像简单查询一样简单,但是如果您的查询对于 group by 和其他许多操作很复杂,而不是使用 linq 可能会很复杂,因此使用这种方式您可以执行查询并在 result 模型中获取结果跨度>
  • 调查您的想法。大部分我都明白。一个(可能很愚蠢,因为我是初学者)问题。我在您的代码(以及其他地方)中看到并下划线 _dbContext 那是什么?另外,如果我写那行,它不喜欢它(名称在当前上下文中不存在)。我在这里尝试了各种事情,但后来遇到了其他问题(比如声明一个 dbcontext 变量)。有什么建议吗?
【解决方案2】:

如果您想返回实体列表,则需要使用ToList()。请参阅我的演示,它使用 dbcontext bu DI 和 linq 查询

1.ClassificationWithLanguageViewModel.cs

public class ClassificationWithLanguageViewModel
{
    public int SuClassificationId { get; set; }
    public string SuClassificationName { get; set; }
}

2.DbContext:

public DbSet<Classification> Classification { get; set; }
public DbSet<ClassificationLanguage> ClassificationLanguage { get; set; }

2.动作:

List<ClassificationWithLanguageViewModel> classificationOne1Language = 
                                          await (from c in _context.Classification
                                          join l in _context.ClassificationLanguage
                                          on c.SuClassificationId equals l.SuClassificationId
                                          select new ClassificationWithLanguageViewModel 
                                          { 
                                            SuClassificationId = c.SuClassificationId,
                                            SuClassificationName =  l.SuClassificationName 
                                          }).ToListAsync();

foreach (var c in classificationOne1Language)
{

}

【讨论】:

  • 嗨@XingZou,我试过了,现在我在 List 行上得到一个 Null 错误。但是当我签入 SQL 分析器时,它显示了一个正确的 SQL 语句,并且在 SQL Studio 中运行该语句时,我得到了 2 条记录。那么,在 SQL 返回记录时,Linq 行怎么会出现 Null 错误。它与 ToList 有关系吗?在另一个解决方案中,他们建议使用 ToListAsync 并等待 _context。我可以想象那将等待结果。但我不知道如何放置 await _context。进入你的 Linq 脚本。有什么建议吗?
  • @Peter le Grand async 和 sync 都可以检索数据。 classificationclassificationLanguage 是什么?参考这个link
  • 分类和分类语言是我正在构建的东西的一小部分。这个想法是内容将在平台中创建。然后可以将这些内容(富文本文章)链接到分类(例如,它是关于气候、污染等的。)但这必须支持多语言,具体取决于用户。因此,如果用户是西班牙人,那么“气候”一词将以西班牙语显示。我会看看你的链接。谢谢。
【解决方案3】:

你的问题有点含糊。您说您基本上希望以下 SQL 查询作为 LINQ。这实际上非常简单:

SELECT 
  Order.CustomerName
, OrderLine.Product 
FROM Order 
JOIN OrderLine 
  ON Order.OrderID = OrderLine.OrderID 
WHERE OrderLine.NotYetDelivered = True

翻译为:

var orders = await _context.Orders
    .Where(o => o.OrderLines.Any(ol => ol.NotYetDelivered))
    .Select(o => new
    {
        CustomerName = o.CustomerName,
        Products = o.OrderLines.Select(ol => ol.Product)
    })
    .ToListAsync();

然而,我有一个潜移默化的怀疑,即您实际上想要的只是尚未交付的订单行。上面的查询和 LINQ 实际上会为您提供订单,这些订单仅包含一个或多个尚未交付的订单行,但它仍将包括 所有 相关的订单行,无论是否他们是否已交付。如果您只想要未交付的订单行,那么您应该从查询订单行开始:

var orderLines = await _context.OrderLines
    .Where(ol => ol.NotYetDelivered)
    .Select(ol => new
    {
        CustomerName = ol.Order.CustomerName,
        Product = ol.Product
    })
    .ToListAsync();

【讨论】:

  • 嗨,克里斯,这个语法看起来有些不同。虽然我特别感兴趣的一件事是 .ToListAsync。我正在尝试 ToList。使用以下答案中建议的重写的 Linq 查询。但是结果是空的。如果我签入 SQL 探查器,它会显示一个基于 Linq 查询的 SQL 查询。这是否与我没有使用的带有 await_context 的 Async 相关?
猜你喜欢
  • 1970-01-01
  • 2014-09-07
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 2021-02-24
相关资源
最近更新 更多