【问题标题】:Querying multiple tables connected by ICollections查询由 ICollections 连接的多个表
【发布时间】:2017-11-26 14:01:09
【问题描述】:

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

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

这是客户类:

[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 表连接的,EF 已将其转换为 public 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;
}

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

【问题讨论】:

    标签: c# sql entity-framework linq


    【解决方案1】:

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

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

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

    它返回一个基于客户用户名的地址列表。

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

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

    希望对你有帮助。

    【讨论】:

    • 谢谢。周一回到课堂时我会试试看。
    • 您想要通过此方法获得客户的地址还是所有地址?
    • 我已经为你写了两个。您可以使用延迟加载方式开发它,但它存在一些性能问题。对于作为学生的你来说,这两种方式都是合理的。祝你好运
    • 所以请注意,如果客户没有地址,它将返回 null。
    【解决方案2】:

    您必须在集合中使用 virtual 以便 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;
    }
    

    【讨论】:

    • 感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 2018-05-30
    相关资源
    最近更新 更多