Starfleet Security Starfleet Security - 1 month ago 18
C# Question

Avoid circular reference for classes

I have a function that creates and returns a "Person". The "Person" has a "Spouse" property which is, of course, another "Person". This causes an endless recursion since the "Person" being created is always a "new" one each time the function is called. Is there a way to use the same function (as shown below) without causing an endless loop?

public PersonModel Load(int personID)
{
PersonModel person = new PersonModel();
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = Helpers.ConnectionDB;
SqlCommand command = new SqlCommand();
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "LoadPerson";
command.Parameters.Add(new SqlParameter("@PersonID", personID));
conn.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
person.PersonID = int.Parse(reader["PersonID"].ToString());
person.FirstName = reader["FirstName"].ToString();
person.LastName = reader["LastName"].ToString();
person.MiddleName = reader["MiddleName"].ToString();
person.Age = reader["Age"] != DBNull.Value ? int.Parse(reader["Age"].ToString()) : (int?)null;
person.SpouseID = reader["SpouseID"] != DBNull.Value ? int.Parse(reader["SpouseID"].ToString()) : (int?)null;
if (person.SpouseID != null && person.Spouse == null)
{
person.Spouse = this.Load(person.SpouseID.Value);
}
}
conn.Close();
}
return person;
}

Dai Dai
Answer

Use a Dictionary<Int32,PersonModel> to keep track of loaded entities:

public PersonModel Load(Dictionary<Int32,PersonModel> dict, int personId) {

    PersonModel ret;
    if( dict.TryGetValue( personId, out ret ) ) return ret;

    // load from database here, but do not call recursively just yet
    ret = new PersonModel() { ... };

    dict.Add( ret.PersonId, ret );

    ret.Spouse = this.Load( dict, person.SpouseId.Value );
}
Comments