在实体模型中实现层次结构

本文关键字:层次结构 实现 实体模型 | 更新日期: 2023-09-27 18:21:17

我需要创建一个模型和方法,该模型和方法将填充相关模型的列表。

我的模型看起来像:

public class SearchHierarchyModel  
{
    public IList<Continent> Continent { get; set; }
    public IList<Country> Country { get; set; }
    public IList<City> City { get; set; }
}

我的方法应该做一些类似的事情:

public IList<SearchHierarchyModel> GetHierarchyFull(int Coninent_Id)
{
    //pseduocode now
    create lists of countries based on continent id
    create lists of cities based on countries id from the prev. step
    return a list of lists with relevant countries and cities
}

型号类别

public class Contient
{
    public int Id { get; set; }
    public string Name { get; set; }
}   
public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ContientId { get; set; }
}
public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CityId { get; set; }
}

也许有更好的方法来实现这种层次结构?有什么办法吗?也许这个模型应该看起来不一样?

在实体模型中实现层次结构

根据关系的设置方式,可以执行类似于.的操作

public IList<SearchHierarchyModel> GetHierarchyFull(int Continent_Id)
{
    var continent = db.Continents.FirstOrDefault(c => c.Id == Continent_Id);
    //Get all countries with a specified ContinentId
    var countryList = db.Countries.Where(c => c.ContinentId == Continent_Id);
    //Get all cities that have a matching CountryId from any country in the first list.
    var cityList = db.Cities.Where(c => countryList.Any(cl => cl.Id == c.CountryId)).ToList();
    //We need to get the original countryList as a true list rather than a collection of entities.
    //If we had called ToList above, it would error out.
    //If we had called ToList in the ForEach loop, we also would have issues.
    var countryList2 = countryList.ToList();
    var searchList = new List<SearchHierarchyModel>
    {
        new SearchHierarchyModel()
        {
            Continent = new List<Continent> { continent },
            Country = countryList2,
            City = cityList
        }
    };
    return searchList;
}

现在对以上内容进行一些评论。在我看来,你只需要一个特定大陆的国家和城市列表。如果是这样的话,实体框架会让您更轻松。

我会把我的核心模型改为:

public class Continent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Country> Countries { get; set; }
} 
public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ContinentId { get; set; }
    public virtual Continent Continent { get; set; }
    public virtual ICollection<City> Cities { get; set; } 
}
public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CountryId { get; set; }
    public virtual Country Country { get; set; }
}

然后我将层次模型设置为:

public class SearchHierarchyModel
{
    public Continent Continent { get; set; }
    public Country Country { get; set; }
    public City City { get; set; }
}

现在我们可以将搜索功能更改为:

public IList<SearchHierarchyModel> GetHierarchyFull(int Continent_Id)
{
    var countries = db.Countries.Where(c => c.ContinentId == Continent_Id);
    var cities = db.Cities.Where(c => countries.Any(co => co.Id == c.Id));
    var searchList = new List<SearchHierarchyModel>();
    foreach (var item in cities)
    {
        var newItem = new SearchHierarchyModel
        {
            Continent = item.Country.Continent,
            Country = item.Country,
            City = item
        };
        searchList.Add(newItem);
    }
    return searchList;
}

现在,我们不是在列表列表上迭代,而是在所有可能返回值的列表上迭代。另外,随着模型的修改,模型之间的关系被明确定义。这意味着我可以更容易地参考他们并与他们互动。


这里有一个搜索方法,它使用Linq反向遍历对象,去掉foreach循环并删除所有多余的列表。

public IList<SearchHierarchyModel> GetHierarchyFull(int Continent_Id)
{
    var continent = db.Continents.FirstOrDefault(c => c.Id == Continent_Id);
    if (continent == null)
        return null;
    var searchList = (from item in continent.Countries
        from city in item.Cities
        select new SearchHierarchyModel
        {
            Continent = continent, 
            Country = item, 
            City = city
        }).ToList();
    return searchList;
}