【问题标题】:Returning a specified type from a method with EF使用 EF 从方法返回指定类型
【发布时间】:2011-11-14 03:18:54
【问题描述】:

如何从具有一对多关系的 LINQ 查询返回方法中的集合?

例如,我有以下代码,其中我可以有多个项目到 TimeTracking 对象。我为返回类型 (IEnumerable) 定义的类型是否有效?它在我的 EF 模型中设置为这种特定的关系。

public IEnumerable<TimeTracking> GetTimeTrackings()
        {
            YeagerTechEntities DbContext = new YeagerTechEntities();

            DbContext.Configuration.ProxyCreationEnabled = false;
            DbContext.Configuration.LazyLoadingEnabled = false;

            var timeTrackings = (from timeTrackingProjects in DbContext.TimeTrackings.Include("TimeTrackings.Projects")
                                 select timeTrackingProjects).Where(p => p.TimeTrackingID > 0);

            CloseConnection(DbContext);

            return timeTrackings;
        }

如果是这样,当我在 MVC 3 视图中显示它并且我的视图包含 IEnumerable&lt;YeagerTech.YeagerTechWcfService.TimeTracking&gt; 模型时,模型变量中是否包含 TimeTracking 和 Project 对象的记录?我不认为它会。我的 TimeTracking 对象设置如下,除非我需要用它继承 Project 类(然后将具有 Project 属性):

    public partial class TimeTracking
        {
            [DataMember]
            public int TimeTrackingID { get; set; }

            [DataMember]
            public short ProjectID { get; set; }

            [DataMember]
            public byte[] Attachment { get; set; }

            [Required]
            [DataType(DataType.Date)]
            [DataMember]
            public System.DateTime StartDate { get; set; }

            [Required]
            [DataType(DataType.Date)]
            [DataMember]
            public System.DateTime EndDate { get; set; }

            [DataMember]
            public string Notes { get; set; }

            [DataMember]
            public System.DateTime CreatedDate { get; set; }

            [DataMember]
            public Nullable<System.DateTime> UpdatedDate { get; set; }

            [DataMember]    
            public virtual Project Project { get; set; }
        }

我还希望我的视图显示与 TimeTracking 相关联的项目文本,而不是项目值。我该怎么做?有人可以帮忙吗?

我在 WCF 客户端上调用方法时收到以下消息。

'如果禁用引用跟踪,则无法序列化'

得到消息后,我修改了我的 DataContracts 以包含引用 ([DataContract(IsReference = true)])。

namespace YeagerTechModel
{
    [Serializable]
    [DataContract(IsReference = true)]
    public partial class Customer
    {
        public Customer()
        {
            this.Projects = new HashSet<Project>();
        }

        [DataMember]
        public short CustomerID { get; set; }

        [Required]
        [StringLength(50)]
        [DataType(DataType.EmailAddress)]
        [DataMember]
        public string Email { get; set; }

我正在执行以下服务器端代码,以成功从我的数据库中以父/子关系获取数据。 Include 方法显式调用获取特定客户的相关项目数据。我必须这样做,因为如果你想通过网络获取你的父/子数据,你必须关闭 LazyLoading。

如果我查看 WCF 消息日志,我可以看到 Customer 对象中的实际数据,并且它在 Customer 对象中包含 Project 对象。

但是,在调用之后,我实际上检查了“客户”变量的内容,我没有看到对任何项目数据的任何引用。

public IEnumerable<Customer> GetCustomers()
        {
            YeagerTechEntities DbContext = new YeagerTechEntities();

            DbContext.Configuration.ProxyCreationEnabled = false;
            DbContext.Configuration.LazyLoadingEnabled = false;

            IQueryable<Customer> customer = DbContext.Customers.Include("Projects").Where(p => p.CustomerID > 0);

            CloseConnection(DbContext);

            return customer;
        }

我现在想做的是引用从调用中返回的项目数据。但是,在输入“客户”后,我没有得到任何客户对象智能感知。这一切都与 IQueryable 对象有关。

我将它作为以下类型传递回我的 MVC 控制器:

IEnumerable<YeagerTechWcfService.Customer> customerList = db.GetCustomers();

并作为以下模型进入我的视图:

IEnumerable<YeagerTech.YeagerTechWcfService.Customer>

现在,最大的问题是“我如何引用返回到我的视图中的项目数据?

以下是我的视图代码,但“item.Project”没有智能感知。请注意,“Email”是我的 Customer 对象中的一个属性。

foreach (var item in Model)
        {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Email)
            </td>

【问题讨论】:

    标签: linq asp.net-mvc-3 linq-to-entities entity-framework-4.1


    【解决方案1】:

    实际上,经过进一步审查,在对象上添加 QucikWatch 后,我现在可以在我的 Customer 集合中看到 Project 集合一直返回到我的客户。

    正确答案是我帖子的最后一部分出现 LazyLoadingEnabled = false。

    【讨论】:

      【解决方案2】:

      看起来你的 Linq 查询应该更接近这个(注意:没有测试查询,可能需要调整):

      var query = (from tt in DbContext.TimeTrackings.Include("Projects")
                   where tt.TimeTrackingID > 0
                   select tt).ToList();
      
      • 您编写的 Linq 查询是延迟执行,您在检索数据之前关闭了连接,因此可能会导致运行时错误。
      • .Include() 语句应指定需要加载的实体上的属性(在您的情况下为 TimeTracking),因此在本例中为 Project 属性

      检索到 TimeTracking 实体的可枚举集合后,您可以访问与特定 TimeTracking 实体关联的 Project 实体的属性,如下所示:

      foreach(var tracking in GetTimeTrackings())
      {
          foreach(var project in tracking.Projects)
          {
              // Assuming your Project entity has a Name property
              Response.Write(project.Name);
          }
      }
      

      我不知道你的意思是什么

      我还希望我的视图显示关联的项目文本 使用 TimeTracking 而不是 Project 值。

      您能否说明您想查看哪个实体的哪些属性?项目实体定义是什么?

      回复您关于在检索数据后关闭连接的评论:

      • 语句IQueryable&lt;Customer&gt; customer = DbContext.Customers.Include("Projects").Where(p =&gt; p.CustomerID &gt; 0); 在您开始迭代它之前实际上不会对数据库执行查询(很可能在您的视图中使用foreach 语句)。如果您在该语句的末尾添加一个.ToList(),它将执行它并返回一个List&lt;Customer&gt;(也是IEnumerable),其中包含您的查询结果的所有记录。
      • 当您尝试键入 customer. 以获取 Customer 实体的智能感知时,您没有看到它,因为 customer 是 Customer 实体的列表(或者更确切地说是它们的 IQueryiable),因此您需要执行类似 @ 的操作987654327@ 访问该列表中第一个客户实体的属性(或对其进行迭代)。
      • 我不是 100% 确定实体引用是如何在 ASP.NET MVC 中在模型实体上通过的,但是您可以完成此操作的一种非常简单的方法是创建一个您想在视图中使用的模型类,比如这个:

        公共类 TimeTrackingModel {

            public int TimeTrackingID { get; set; }
            public string ProjectName { get; set; }
        

        }

      然后在您的查询中执行以下操作:

      var customers = (from tt in DbContext.TimeTrackings.Include("Projects")
                       where tt.TimeTrackingID > 0
                       select new TimeTrackingModel { TimeTrackingID = tt.TimeTrackingID, ProjectName = tt.Project.ProjectName }).ToList();
      

      然后在您的视图中指定 IEnumberable&lt;TimeTrackingModel&gt; 作为模型,然后像这样访问属性:

      foreach (var item in Model)
              {
              <tr>
                  <td>
                      @Html.DisplayFor(modelItem => item.ProjectName)
                  </td>
      

      【讨论】:

      • +1 表示延迟执行/关闭连接警告 :) 另一个补充:在 EF 4.1 中,我始终建议使用强类型版本的 Include:Include(t =&gt; t.Projects)
      • 我在获取数据后正在关闭连接...即使在关闭连接后,我也可以在调试时看到我返回的数据。我要为我想做的指定事情编辑我的帖子。如果你能帮助我,那就太好了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-23
      • 2021-12-14
      • 1970-01-01
      相关资源
      最近更新 更多