dbcontext使用select(),include()和where()无法正常加载相关实体

时间:2012-07-16 00:03:21

标签: entity-framework linq-to-entities dbcontext

我在实体之间有以下关系。 公司1 --- *任命* --- 1名员工

我在单独的数据库中拥有.net asp成员资格。无论何时创建用户,都可以将其分配给公司,员工或管理员角色。

在我的公司控制器的索引操作中,我检查登录用户的角色。根据角色,我做了不同的linq查询。例如,管理员可以获得所有公司的列表,公司可以获得具有与User.Identity.Name相同的用户名属性(字符串)的公司列表。对于管理员和公司角色,它都运行良好。

对于员工角色,我想加载与当前员工相关的所有公司。我很难编写一个执行此工作的linq查询。

我试过

var companies = db.Companies.Include(c => c.Appointments.Select(a=>a.Employee).Where(e=>e.Username.ToLower() == this.User.Identity.Name.ToLower())).ToList();

我得到这个错误 “Include路径表达式必须引用在类型上定义的导航属性。使用虚线路径作为参考导航属性,使用Select运算符作为集合导航属性。 参数名称:路径“

以下是源代码

CompanyController

[Authorize]
public class CompanyController : Controller
{
    private MyDBContext db = new MyDBContext();

    //
    // GET: /Company/

    public ViewResult Index()
    {
        var viewModel = new CompanyIndexViewModel();
        if (Roles.IsUserInRole("administrators")) {
            viewModel = new CompanyIndexViewModel { Companies = db.Companies.ToList() };
        }
        else if (Roles.IsUserInRole("companies")) {
            viewModel = new CompanyIndexViewModel { Companies = db.Companies.Where(c => c.Username.ToLower().Equals(this.User.Identity.Name.ToLower())).ToList() };
        }
        else if (Roles.IsUserInRole("employees")) {
            var companies = db.Companies.Include(c => c.Appointments.Select(a=>a.Employee).Where(e=>e.Username.ToLower() == this.User.Identity.Name.ToLower())).ToList();
            viewModel = new CompanyIndexViewModel { Companies = companies.ToList() };
        }

        return View(viewModel);
    }

...

模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace TorontoWorkforce.Models
{
    public class Company
    {
        public int CompanyId { get; set; }

        [Required]
        public string Username { get; set; }

        [Display(Name="Company Name")]
        [Required]
        public string Name { get; set; }


        [UIHint("PhoneNumber")]
        public string Phone { get; set; }

        [DataType(DataType.Url)]
        public string Website { get; set; }

        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }

        public AddressInfo AddressInfo { get; set; }

        public virtual ICollection<Contact> Contacts { get; set; }

        public virtual ICollection<Appointment> Appointments { get; set; }

        public Company(){
            this.AddressInfo = new AddressInfo();
        }
    }
}



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace TorontoWorkforce.Models
{
    public class Appointment
    {

        public int AppointmentId { get; set; }


        [Required]
        [UIHint("DateTime")]
        [Display(Name="Appointment Date")]
        public DateTime? DateOfAppointment { get; set; }

        [Required]
        public int CompanyId { get; set; }

        [Required]
        public int EmployeeId { get; set; }

        [Required]
        [UIHint("MultilineText")]
        [Display(Name = "Appointment Summary")]
        public string Description { get; set; }

        [Display(Name="Allocated No of Hours")]
        public decimal NoOfHoursWorked { get; set; }

        public virtual Company Company { get; set; }

        public virtual Employee Employee { get; set; }

        public virtual ICollection<AppointmentLine> AppointmentLines { get; set; }

        public Appointment() {
            //this.AppointmentLines = new List<AppointmentLine>();
            this.DateOfAppointment = DateTime.Now;
        }

        [NotMapped]
        [Display(Name="Actual No of Hours")]
        public decimal ActualHoursWorked {
            get
            {
                decimal total = 0;
                foreach (var jobline in this.AppointmentLines)
                {
                    total = total + jobline.TimeSpent;
                }
                return total;
            } 
        }


    }

    public class AppointmentLine
    {
        public int AppointmentLineId { get; set; }

        [UIHint("MultilineText")]
        [Required]
        public string Description { get; set; }

        [Display(Name="Time Spent")]
        [DataType(DataType.Duration)]
        public decimal TimeSpent { get; set; }

        public int AppointmentId { get; set; }

        public virtual Appointment Appointment { get; set; }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace TorontoWorkforce.Models
{
    public class Employee: TorontoWorkforce.Models.Person
    {
        public int EmployeeId { get; set; }

        [Required]
        public string Username { get; set; }

        [Display(Name="Date Hired")]
        public DateTime? DateHired { get; set; }

        [Required]
        public string Position { get; set; }

        public virtual ICollection<Appointment> Appointments { get; set; }

        public Employee() {
            this.DateHired = DateTime.Now;        
        }
    }
}

2 个答案:

答案 0 :(得分:6)

如果您希望获得与所选员工预约的公司,则无需使用Include。 Include用于指示EF加载与公司相关的所有约会(以及it doesn't support filtering)。试试这个:

string userName = this.User.Identity.Name.ToLower();
var companies = db.Companies.Where(c => c.Appointments.Any(a => 
                   a.Employee.Username.ToLower() == userName)).ToList();

答案 1 :(得分:0)

我认为你在错误的地方有一个末端括号。在“a =&gt; a.Employee”之后你需要一个,在“this.User.Identity.Name.ToLower())之后需要一个;”

试试这段代码:

var companies = db.Companies.Include(c => c.Appointments.Select(a=>a.Employee)).Where(e=>e.Username.ToLower() == this.User.Identity.Name.ToLower()).ToList();      

编辑: 您还应该能够使用标准字符串include方法:

var companies = db.Companies.Include("Appointments.Employee").Where(e=>e.Username.ToLower() == this.User.Identity.Name.ToLower()).ToList();