【问题标题】:Passing joined table to view as model Asp.Net Core传递连接表以查看模型 Asp.Net Core
【发布时间】:2021-04-03 16:32:13
【问题描述】:

我有 2 个通过 linq 查询加入的表:

var catData = from c in _context.ProductCategory
              join d in _context.ProductCategoryData
                     on c.Id equals d.ProductCategoryId into g
              from gg in g.DefaultIfEmpty()
              select new { c.Id, c.Name, gg.Path };

我想将此查询的结果作为模型传递给查看。问题是视图需要我传递的模型类型强烈指定。

我听说可以引入另一个包含 2 个表模型的类,然后将 2 个表加入这个类。但是,在我看来,它效率不高,因为我将始终拥有两个表中的所有列,而我只需要特定的列。

我想到的另一个选项 - 使用 ExpandoObject,如下所示:

dynamic model = new ExpandoObject();
model = catData.ToList();

return View("Categories", model);

然后像这样访问视图中的动态对象:

@model dynamic;

@foreach (var i in Model)
{
   <img src="@i.Path">
       <p>@i.Name</p>
}

但是这会引发模型对象不包含路径或名称的错误。

有没有其他方法可以解决这个问题?

【问题讨论】:

  • 为什么不在查询之后再映射一次数据呢?只需在 catData 上使用 Select 并将其映射到视图所需的对象 - 这将解决您的问题:强类型模型,也只是加载所需的数据

标签: c# entity-framework linq asp.net-core entity-framework-core


【解决方案1】:

最好的方法是创建一个新的 CatData 和 ViewModel 类

public class CatData
{
public int Id {get; set;}
public string Name {get; set;}
public string Path {get; set;}
}

public class CatDataViewModel
{
  public IEnumerable<CatData> CatDataList {get; set;}
}

修正您的查询

var catData = ( from ...
              select new CatData { Id= c.Id, Name =c.Name, Path= gg.Path }
              ).ToList();

var model= new CatDataViewModel { CatDataList=catData };

并查看

@model CatDataViewModel;

@foreach (var i in Model.CatDataList)
{
   <img src="@i.Path">
       <p>@i.Name</p>
}

【讨论】:

    【解决方案2】:

    您需要的是IEnumerable&lt;dynamic&gt; 而不是dynamicdynamic 仅用作暴露属性/方法的对象,不能是任意对象的IEnumerable。如您所见,ExpandoObject 实际上是键值对的IEnumerable(成员名称和成员值之间的映射)。但这不是你想要的IEnumerable

    这段代码:

    dynamic model = new ExpandoObject();
    model = catData.ToList();
    

    实际上会将您的model 设置为{ c.Id, c.Name, gg.Path } 的列表。所以它不像你想象的那样是动态的。

    以下是构建IEnumerable&lt;dynamic&gt; 的方法:

    var model = catData.Select(e => {
                   dynamic o = new ExpandoObject();
                   o.Id = e.Id;
                   o.Name = e.Name;
                   o.Path = e.Path;
                   return o;
                });
    

    该模型是一个真正的IEnumerable&lt;dynamic&gt;,它现在应该可以工作了。

    您还可以编写一个扩展方法将普通的IEnumerable&lt;T&gt; 转换为IEnumerable&lt;dynamic&gt; 以使用这种特殊的场景,如下所示:

    public static class DynamicEnumerableExtensions {
         public static IEnumerable<dynamic> AsDynamic<T>(this IEnumerable<T> items) {
                var props = typeof(T).GetProperties();
                foreach(var item in items)
                {
                    var o = new ExpandoObject();
                    //set properties for the dynamic item
                    foreach(var prop in props)
                    {
                        o.TryAdd(prop.Name, prop.GetValue(item));
                    }
                    yield return o;
                }
         }
    }
    

    并像这样使用它:

    var model = catData.AsDynamic();
    

    使用这种方便的方法,您不必每次都手动重写逻辑,例如任意匿名对象的新列表(具有未知数量的属性)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 2015-06-21
      • 2021-06-11
      相关资源
      最近更新 更多