查询由ICollections连接的多个表

时间:2017-06-23 05:39:17

标签: c# sql entity-framework linq

我正在开发这个项目,我们首先获得了一个与EF数据库连接的数据库。

我正在尝试检索给定客户的地址。

以下是Customer类:

[DataContract]
public partial class Customer
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Customer()
    {
        this.Orders = new HashSet<Order>();
        this.WishLists = new HashSet<WishList>();
        this.Addresses = new HashSet<Address>();
        this.Contacts = new HashSet<Contact>();
    }

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

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

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

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

    [DataMember]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public ICollection<Order> Orders { get; set; }

    [DataMember]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public ICollection<WishList> WishLists { get; set; }

    [DataMember]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public ICollection<Address> Addresses { get; set; }

    [DataMember]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public ICollection<Contact> Contacts { get; set; }
}

地址类:

[DataContract]
public partial class Address
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Address()
    {
        this.Orders = new HashSet<Order>();
        this.Customers = new HashSet<Customer>();
        this.Employees = new HashSet<Employee>();
    }

    [DataMember]
    public int AddressID { get; set; }

    [DataMember]
    public int AddressType { get; set; }

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

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

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

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

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

    [DataMember]
    public AddressType AddressType1 { get; set; }

    [DataMember]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public ICollection<Order> Orders { get; set; }

    [DataMember]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public ICollection<Customer> Customers { get; set; }

    [DataMember]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public ICollection<Employee> Employees { get; set; }
}

数据库中的这两个表通过CustomerAddress表连接,该表已转变为公共ICollection Customers {get;组;和公共ICollection地址{get;组; }。

我的目标是在我的MVC Web应用程序中显示客户的地址。但是,我在尝试编写LINQ查询或等效项以检索地址时遇到了很多麻烦。到目前为止,我已经尝试过:

// Return the details for current customer (this function works as expected)
public Customer CurrentCustomer(string UserName)
{
    Customer data = (from c in db.Customers
                     where c.UserName == UserName
                     select c).SingleOrDefault(); 

    return data;
}

// Return the address details for current customer (this function does not work)
public Address GetAddress(string UserName)
{
    // function to retrieve the CustomerID of the current customer
    var customerID = CurrentCustomer(UserName).CustomerID;

    Address data = db.Customers.Find(customerID).Addresses.FirstOrDefault();

    return address;
}

提前感谢您的帮助。我正在努力查询没有外键关系的两个表。

2 个答案:

答案 0 :(得分:1)

您不需要首先找到Username的客户,然后传入以查找其地址。你可以通过简单的查询找到它。

要仅提取客户的地址,请将方法更改为:

    public List<Address> GetAddresses(string UserName)
    {
        var addresses = db.Customers.Where(p=> p.UserName == UserName).SelectMany(a=> a.Addresses).ToList();

        return addresses;
    }

它根据客户UserName返回地址列表。

您可以使用以下方法返回客户的其中一个地址:

public Address GetAddress(string UserName)
{
    var address = db.Customers.Where(p=> p.UserName == UserName).Select(a=> a.Addresses.FirstOrDefault()).FirstOrDefault();

    return address;
}

我希望它有所帮助。

答案 1 :(得分:1)

您必须在EF的集合中使用虚拟,以便通过外键为导航属性提供延迟加载

[DataMember]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Address> Addresses { get; set; }

之后你可以使用像这样的查询

public Address GetAddress(string UserName)
{
   Address data = db.Customers.Find(c => c.UserName == UserName)?.Addresses?.FirstOrDefault();

   return address;
}