【问题标题】:MVC4 linq query to object doesn't come out as the correct objectMVC4 linq 对对象的查询没有作为正确的对象出现
【发布时间】:2013-07-31 06:50:46
【问题描述】:

错误:传入字典的模型项的类型为“System.Data.Entity.Infrastructure.DbQuery (snip) ...正在查找类型“Advocate”

控制器方法如下所示:

[HttpGet]
public ActionResult AdvocateEdit(int id)
{
    var advocate = from a in db.Query<Advocate>().Include(a => a.AdvocateId)
                   where (a.AdvocateId == id)
                   select a;

    return View(advocate);
}

视图确实是输入到 Advocate @model 的,在逐步完成之后,我很确定问题出在这个查询上。返回时必须是 Advocate 类型。

db.Query is an IQueryable<T> method in my DbContext that returns Set<T>().

如果需要更多信息,请告诉我。谢谢大家

添加----

DbContext.cs

public interface IAcmeDb : IDisposable
{
    IQueryable<T> Query<T>() where T : class;
}

public class AcmeDb : DbContext, IAcmeDb
{
    public AcmeDb() : base("name=AcmeDB") {}
    public DbSet<Advocate> Advocates { get; set; }

    IQueryable<T> IAcmeDb.Query<T>()
    {
         return Set<T>();
    }
}

【问题讨论】:

    标签: c# asp.net-mvc linq iqueryable


    【解决方案1】:

    至少有一个值得注意的问题。 LINQ 倾向于使用延迟执行。我在您的代码中没有看到您强制执行查询。除非您在 View(advocate) 的某个地方枚举查询产生的 IEnumberable&lt;T&gt;,否则您将不会处理 Advocate 类型的对象。

    我建议在查询末尾添加一个ToList()ToArray() 调用,这将确保它实际被执行。如果这不起作用,我会将查询分开并确保 db.Query&lt;Advocate&gt;() 返回您所期望的。

       List<Advocate> = db.Query<Advocate>().Include(a => a.AdvocateId)
                        .Where(a.AdvocateId == id)
                        .Select(a => a).ToList();
    

    我已将您的查询转换为方法语法,因为它是我所熟悉的。上面的例子可能会解决你的问题。我认为要保留查询语法,您应该将整个左侧放在父母中,然后添加 ToList() 调用,但是我不确定正确的语法是什么。

    编辑:基于其他 cmets,问题不是延迟执行,而是尝试将集合传递给寻找单个实例的方法。使用上面相同的代码,您只需将ToList() 更改为FirstOrDefault(),您的代码就可以工作了;

    List<Advocate> = db.Query<Advocate>().Include(a => a.AdvocateId)
                            .Where(a.AdvocateId == id)
                            .Select(a => a).FirstOrDefault();
    

    注意:引用类型的默认值为null,如果您没有适当的空值检查,这当然可能会给您带来问题。

    【讨论】:

    • 最初我只是在使用 db.Advocates.Find(id) 并且工作得很好,但后来我不得不去幻想并设置一个 db 接口,这样我就可以针对一个假分贝。可能应该把所有东西都换回来,这样我就可以继续前进
    • 但是您的代码仍然是 Advocate 的集合而不是 Advocate,因此它不会修复错误。此外,即使视图确实采用了集合,通常也不需要在控制器中具体化查询。如果视图需要实体,它将枚举查询。如果它不需要它们,那么在控制器中执行查询是浪费的。也许视图会应用进一步的过滤器或其他东西,在这种情况下,您的方法将获取比必要更多的实体,
    • @MikeGoodwin 好点。我忽略了他的观点是在寻找单身人士的事实。
    【解决方案2】:

    我认为您想将 Advocate 元素传递给视图,而不是查询本身。试试这个:

    return View(advocate.First());
    

    代码中的advocate 对象是IQueryable 类型,如果您的视图需要Advocate 对象,只需使用First() 或FirstOrDefault() 获取查询的第一个元素。

    【讨论】:

    • 返回断点的类型为 System.Data.Entity.Infrastructure.DbQuery。 advocate.First() 抛出无效操作{“指定的包含路径无效。EntityType 'Acme.Web.Models.Advocate' 未声明名为 'AdvocateId' 的导航属性。”}
    • 你想用 .Include(a => a.AdvocateId) 达到什么目的?我认为你不需要。
    • 只是想获取一个特定的记录...已经做了一段时间的低级 Windows 服务编程,所以我的 linq 已经很生疏了。
    【解决方案3】:

    如果您的视图需要单个 Advocate 并且给定 id 始终只有一个实体,那么您想要:

    [HttpGet]
    public ActionResult AdvocateEdit(int id)
    {
       try
       {
           Advocate advocate = db.Query<Advocate>().Single(a => a.AdvocateId == id);
           return View(advocate);
       }
       catch(InvalidOperationException ex)
       {
          //handle the case where no entity matches the supplied id (return status code 404?), or
          //there are no Advocates at all (redirect to a create page?), or
          //more than one entity matches (return status code 500)
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-08
      • 1970-01-01
      • 1970-01-01
      • 2011-08-24
      • 2020-12-06
      • 2014-05-07
      • 1970-01-01
      相关资源
      最近更新 更多