使用LINQ选择特定的对象图



我有一个像这样连接的经典业务对象图:

public enum TypeVoie
{
    rue,
    avenue,
    route,
    împasse
}
public class Ville
{
    string nom;
    public string Nom { get { return nom; } }
    string codePostal;
    bool capital;

    public  string  id()
    {
        return nom + codePostal + capital.ToString();
    }
}
/// <summary>
/// classe composé
/// </summary>
public class Adresse
{
    int noRue;
    string nomRue;
    TypeVoie typeVoie;
    public  Ville ville { get; set; }
    public  Personne habitant { get; set; }
    public Personne Habitant { get => habitant; set => habitant = value; }
    public  string  id()
    {
        return noRue.ToString() + nomRue + typeVoie.ToString() + ville.id();
    }
}
/// <summary>
/// classe de base composant
/// </summary>
public class Personne
{
    /// <summary>
    /// l'attribut ne marche pas
    /// </summary>
    public string nom { get; set; }
    public string prenom { get; set; }
    Dictionary<string, Adresse> adresses = new Dictionary<string, Adresse>();
    public Dictionary<string, Adresse> Adresses { get => adresses; set => adresses = value; }
}
/// <summary>
/// classe composant
/// </summary>
public class Patient: Personne
{
    private static   int no = 0;
    private string noSS;
    public string IPP;
    public string NoSS { get => noSS; set => noSS = value; }
    public  string  LibelleIdentifiant { get; set; }
}

之后,我定义了此对象图的内存模型

/// <summary>
/// initialize a model
/// </summary>
public class InitModel1: InitModel
{
    public Patient patient1;
    public Patient patient2;
    public Patient patient3;
    public Patient patient4;
    public List<Patient> patients = new List<Patient>();
    public  InitModel1()
    {
        Ville paris = new Ville("Paris", "78000", true);
        Ville lyon = new Ville("Lyon", "69000", false);
        Adresse adresse1 = new Adresse(10, "rue de la paix", TypeVoie.rue, paris);
        Adresse adresse2 = new Adresse(69, "rue marietton", TypeVoie.rue, lyon);
        Adresse adresse3 = new Adresse(35, "avenue de saxe", TypeVoie.avenue, lyon);
        patient1 = new Patient("Berton", "isabelle", adresse1, "22372727320");
        patient2 = new Patient("moussu", "marthe", null, null);
        patient3 = new Patient("mornard", "xavier", adresse2, "66666242");
        patient4 = new Patient("gallot", "frederic", adresse3, "45313248");
        Adresse adresse4 = new Adresse(28, "impasse bellevue", TypeVoie.împasse, lyon);
        patient4.Adresses.Add(adresse4.id(), adresse4);
        patients.Add(patient1);
        patients.Add(patient2);
        patients.Add(patient3);
        patients.Add(patient4);
    }
}

我想向内存中的对象图提出LINQ请求,以便制作模型的部分副本。所以我写了这样的linq请求:

 List<Patient> patientsCherches = patients;
 var patientsTrouves = (from p in patientsCherches
                        where p.lstAddresses.FirstOrDefault(a => a.ville.Nom == "Lyon") != null
                         select p)
                                 .ToList();

请求有效,只返回具有良好地址的患者,但我在此请求中有两个问题:

  • 请求返回detter4对象的两个地址,即使第二个地址不在里昂上:如何修改Where子句仅返回好地址?
  • 我只想在不连接地址的情况下返回患者对象,我该怎么做?因为LINQ请求可以返回对象集合,但无需复制或修改它们,所以我不知道如何返回没有链接对象的对象的副本

如果查询要进入数据库,则可以在服务器端进行此过滤。在这种情况下,但是数据已经在内存中,因此,如果您不想丢失原始实例的数据,则必须创建一个新实例。

仅选择地址

您将创建一个新的Patient实例,并将地址列表设置为过滤结果。

var patientsTrouves = (from p in patientsCherches
             where p.lstAddresses.FirstOrDefault(a => a.ville.Nom == "Lyon") != null
             select new Patient( /* initialize patient using "p" values */ ) { IPP = p.IPP, NoSS = p.NoSS, 
             lstAddresses = p.lstAddresses.Where( a => a.ville.Nom == "Lyon" ).ToList() } )
                                 .ToList();

只有没有地址的患者

在这里您可以简单地创建一个新的患者实例而不初始化地址列表。

var patientsTrouves = (from p in patientsCherches
             where p.lstAddresses.FirstOrDefault(a => a.ville.Nom == "Lyon") != null
             select new Patient( /* initialize patient using "p" variable */ ) )
                                 .ToList();

其他建议

我还有一些有关您的代码的建议,就像可以改善可读性的潜在改进:

  • 明确的命名惯例。通常,属性和方法使用PascalCasingConvention(每个单词都有首字母(,而私有字段使用camelCasingConvention(每个单词都有首字母,除第一个字母外(
  • 理想情况下,方法名称应包括动词,以指示它们执行动作的事实,并且实际上是方法,而不是属性。例如,Id()更可读性为GetId()
  • 该属性的名称应具有自描述性,并且如果不需要的话,则不必描述数据类型 - 不需要lstAddresses,您可以仅使用Addresses,因为很明显,还有更多。
  • 避免使用IPP之类的公共字段。您几乎可以始终使用公共财产。它是更适合未来的。
  • 而不是FirstOrDefault( condition ) != null您可以使用Any( condition )

最新更新