需要类设计帮助

时间:2009-01-18 23:48:52

标签: asp.net oop

我是编程的新手,所以我想我会从那些知道它的人那里得到帮助。

我目前正在编写一个注册应用程序,它基本上会接受用户输入, 验证输入的数据,显示审阅屏幕(用户必须打印出来并邮寄到副本中),然后将输入的信息保存到数据库中。

以下是需要捕获和保存的字段。

public class Person 
{
   private string id;
   private string currentLastName;
   private string currentFirstName;
   private string currentMiddleName;
   private string currentSuffixtName;

   private string formerLastName;
   private string formerFirstName;
   private string formerMiddleName;
   private string formerSuffixtName;

   private string currentAddressNumber;
   private string currentAddressDirection;
   private string currentAddressStreet;
   private string currentAddressStreetType;
   private string currentAddressAptNum;
   private string currentAddressrCity;
   private string currentAddressState;
   private string currentAddressZipcode;
   private string currentAddressCounty;

   private string formerAddressNumber;
   private string formerAddressDirection;
   private string formerAddressStreet;
   private string formerAddressStreetType;
   private string formerAddressAptNum;
   private string formerAddressrCity;
   private string formerAddressState;
   private string formerAddressZipcode;
   private string formerAddressCounty;

   private string mailAddressLineOne;
   private string mailAddressLineTwo;
   private string mailAddressLineThree;

   private DateTime birthdate;
   private string gender;
    private string HomePhone;
    private string WorkPhone;
    private string CellPhone;
    private string FaxNumber;
   private string driversLicense;
   private string ssNumber;
   private string membershipType;
   private DateTime registrationDate;
   private string ipAddress;
   private string browserInfo; 
}

在给出另一眼之后,我想我会将常见的东西分开并为每个人创建一个类,并让一个Person拥有每个类或类的接口。即。

public interface IName
{
    string getLastName();
    string getFirstName();
    string getMiddleName();
    string getSuffixName();
}

    public class Name : IName
{
    private string _lastName;
    private string _firstName;
    private string _middleName;
    private string _suffixName;

    // Validation Methods
    // private set methods

    //#region IName Members
}


public interface IAddress
{
    string getAddressNumber();
    string getAddressDirection();
    string getAddressStreet();
    string getAddressStreetType();
    string getAddressAptNum();
    string getAddressCity();
    string getAddressState();
    string getAddressZipcode();
    string getAddressCounty();
}

public class Address : IAddress
{
    private string _addressNumber;
    private string _addressDirection;
    private string _addressStreet;
    private string _addressStreetType;
    private string _addressAptNum;
    private string _addressrCity;
    private string _addressState;
    private string _addressZipcode;
    private string _addressCounty;

    // Validation Methods
    // private Set Methods
    // public get methods


    //#region IAddress Members
}
public interface IPerson
{
    int getId();
    IName getCurrentName();
    IName getFormerName();

    IAddress getCurrentAddress();
    IAddress getFormerAddress();
    IAddress getMailingAddress();

    DateTime getBirthdate();
    string getGender();
    string getSSNumber();
    string getPersonType();
    DateTime getRegistrationDate();
    string getIPAddress();
    string getBrowserInfo();
    string getDriversLicense();

    string getHomePhone();
    string getWorkPhone();
    string getCellPhone();
    string getFaxNumber();
    string getEmailAddress();
    string getSecondaryEmailAddress();

    bool save();
    void load();

}

public class Person : IPerson
{
    private int _id;
    private IName _currentName;
    private IName _formerName;

    private IAddress _currentAddress;
    private IAddress _formerAddress;
    private IAddress _mailingAddress;

    private DateTime _birthdate;
    private string _gender;
    private string _ssNumber;
    private string _personType;
    private DateTime _registrationDate;
    private string _ipAddress;
    private string _browserInfo;
    private string _driversLicense;

    private string _homePhone;
    private string _workPhone;
    private string _cellPhone;
    private string _faxNumber;
    private string _emailAddress;
    private string _secondaryEmailAddress;


    // private set methods

    // #region IPerson Members
    // .... Get Methods 
    public bool save()
    {
        DataLayer dl = new DataLayer();
        if (_id == 0)
            return dl.insertPerson(this);
        else
            return dl.updatePerson(this);
    }
}

这是我的数据层插入方法

public bool insertPerson(IPerson person)
{
    bool inserted = false;
    SqlConnection cnDB = DatabaseConnection.GetOpenDBConnection();
    try
    {
        SqlCommand cmDB = new SqlCommand("sp_InsertName", cnDB);
        cmDB.CommandType = CommandType.StoredProcedure;
        cmDB.Parameters.Add("@last_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@last_name"].Value = person.getCurrentName().getLastName();
        cmDB.Parameters.Add("@first_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@first_name"].Value = person.getCurrentName().getFirstName();
        cmDB.Parameters.Add("@middle_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@middle_name"].Value = person.getCurrentName().getMiddleName();
        cmDB.Parameters.Add("@suffix_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@suffix_name"].Value = person.getCurrentName().getSuffixName();
        int id = cmDB.ExecuteNonQuery();

        cmDB = new SqlCommand("sp_InsertName", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@last_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@last_name"].Value = person.getFormerName().getLastName();
        cmDB.Parameters.Add("@former_first_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@former_first_name"].Value = person.getFormerName().getFirstName();
        cmDB.Parameters.Add("@middle_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@middle_name"].Value = person.getFormerName().getMiddleName();
        cmDB.Parameters.Add("@suffix_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@suffix_name"].Value = person.getFormerName().getSuffixName();
        cmDB.ExecuteNonQuery();

        // Insert Current Address

        cmDB = new SqlCommand("sp_InsertAddress", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@address_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_number"].Value = person.getCurrentAddress().getAddressNumber();
        cmDB.Parameters.Add("@address_direction", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_direction"].Value = person.getCurrentAddress().getAddressDirection();
        cmDB.Parameters.Add("@address_street", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street"].Value = person.getCurrentAddress().getAddressStreet();
        cmDB.Parameters.Add("@address_street_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street_type"].Value = person.getCurrentAddress().getAddressStreetType();
        cmDB.Parameters.Add("@address_apt_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_apt_number"].Value = person.getCurrentAddress().getAddressAptNum();
        cmDB.Parameters.Add("@address_city", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_city"].Value = person.getCurrentAddress().getAddressCity();
        cmDB.Parameters.Add("@address_state", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_state"].Value = person.getCurrentAddress().getAddressCity();
        cmDB.Parameters.Add("@address_zipcode", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_zipcode"].Value = person.getCurrentAddress().getAddressZipcode();
        cmDB.Parameters.Add("@address_county", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_county"].Value = person.getCurrentAddress().getAddressCounty();
        cmDB.ExecuteNonQuery();

        // Insert Former Address

        cmDB = new SqlCommand("sp_InsertAddress", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@address_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_number"].Value = person.getFormerAddress().getAddressNumber();
        cmDB.Parameters.Add("@address_direction", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_direction"].Value = person.getFormerAddress().getAddressDirection();
        cmDB.Parameters.Add("@address_street", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street"].Value = person.getFormerAddress().getAddressStreet();
        cmDB.Parameters.Add("@address_street_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street_type"].Value = person.getFormerAddress().getAddressStreetType();
        cmDB.Parameters.Add("@address_apt_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_apt_number"].Value = person.getFormerAddress().getAddressAptNum();
        cmDB.Parameters.Add("@address_city", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_city"].Value = person.getFormerAddress().getAddressCity();
        cmDB.Parameters.Add("@address_state", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_state"].Value = person.getFormerAddress().getAddressCity();
        cmDB.Parameters.Add("@address_zipcode", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_zipcode"].Value = person.getFormerAddress().getAddressZipcode();
        cmDB.Parameters.Add("@address_county", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_county"].Value = person.getFormerAddress().getAddressCounty();
        cmDB.ExecuteNonQuery();

        // Insert Mailing Address

        cmDB = new SqlCommand("sp_InsertAddress", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@address_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_number"].Value = person.getMailingAddress().getAddressNumber();
        cmDB.Parameters.Add("@address_direction", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_direction"].Value = person.getMailingAddress().getAddressDirection();
        cmDB.Parameters.Add("@address_street", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street"].Value = person.getMailingAddress().getAddressStreet();
        cmDB.Parameters.Add("@address_street_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_street_type"].Value = person.getMailingAddress().getAddressStreetType();
        cmDB.Parameters.Add("@address_apt_number", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_apt_number"].Value = person.getMailingAddress().getAddressAptNum();
        cmDB.Parameters.Add("@address_city", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_city"].Value = person.getMailingAddress().getAddressCity();
        cmDB.Parameters.Add("@address_state", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_state"].Value = person.getMailingAddress().getAddressCity();
        cmDB.Parameters.Add("@address_zipcode", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_zipcode"].Value = person.getMailingAddress().getAddressZipcode();
        cmDB.Parameters.Add("@address_county", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@address_county"].Value = person.getMailingAddress().getAddressCounty();
        cmDB.ExecuteNonQuery();

        // insert Personal Info

        cmDB = new SqlCommand("sp_InsertPersonalInfo", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@birthdate", System.Data.SqlDbType.DateTime);
        cmDB.Parameters["@birthdate"].Value = person.getBirthdate();
        cmDB.Parameters.Add("@gender", System.Data.SqlDbType.VarChar, 1);
        cmDB.Parameters["@gender"].Value = person.getGender();
        cmDB.Parameters.Add("@ss_number", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@ss_number"].Value = person.getSSNumber();
        cmDB.Parameters.Add("@person_type", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@person_type"].Value = person.getPersonType();
        cmDB.Parameters.Add("@registration_date", System.Data.SqlDbType.DateTime);
        cmDB.Parameters["@registration_date"].Value = person.getRegistrationDate();
        cmDB.Parameters.Add("@ip_address", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@ip_address"].Value = person.getIPAddress();
        cmDB.Parameters.Add("@browser_info", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@browser_info"].Value = person.getBrowserInfo();
        cmDB.Parameters.Add("@drivers_license", System.Data.SqlDbType.VarChar, 20);
        cmDB.Parameters["@drivers_license"].Value = person.getDriversLicense();
        cmDB.ExecuteNonQuery();

        //insert email address contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Email";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@gender"].Value = person.getEmailAddress();
        cmDB.ExecuteNonQuery();

        //insert secondary email address contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Secondary Email";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@gender"].Value = person.getSecondaryEmailAddress();
        cmDB.ExecuteNonQuery();

        //insert home phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Home Phone";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getHomePhone();
        cmDB.ExecuteNonQuery();

        //insert work phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Work Phone";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getWorkPhone();
        cmDB.ExecuteNonQuery();

        //insert cell phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Cell Phone";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getCellPhone();
        cmDB.ExecuteNonQuery();

        //insert cell phone contact type
        cmDB = new SqlCommand("sp_InsertContactType", cnDB);
        cmDB.Parameters.Add("@person_id", System.Data.SqlDbType.Int);
        cmDB.Parameters["@person_id"].Value = id;
        cmDB.Parameters.Add("@contact_type", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact_type"].Value = "Fax Number";
        cmDB.Parameters.Add("@contact", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@contact"].Value = person.getFaxNumber();
        cmDB.ExecuteNonQuery();


        inserted = true;
    }
    catch (SqlException sqlEx)
    {
        throw new Exception(GetSqlExceptionMessage(sqlEx.Number));
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        if (cnDB.State == ConnectionState.Open)
            cnDB.Close();
    }
    return inserted;
}

编辑:我觉得这段代码以后很难维护。 任何人都可以帮我找出一个更简单/可维护的方法吗? 我也很难知道如何在添加记录后更新记录。

提前感谢您提供任何帮助

7 个答案:

答案 0 :(得分:3)

首先,如果您想简化维护,我会考虑使用ORM来进行映射。我会看看nHibernate,Linq2Sql,Entity Framework或其他十亿左右的其中一个。它会从上面消除很多噪音。

第二个建议是继续你正在进行的重构。我喜欢你如何取消地址,如果你看看你的人,一个人没有以前的名字,你的做法是在你的域模型中泄漏跟踪以前信息的要求。我会把所有这些都移出来,并定义一个DTO,它有两个属性:

public class PersonDTO
{
    public Person Current;
    Public Person Previous;
}

我认为这可以清除很多噪音。我还想使用字典处理多个电话号码,基本上我们有:

public class Phone
{
   PhoneType PhoneType;
   string Number
   string AreaCode
   string Extension
}

有些人可能会使手机有数字,所以我不想辩论,或者你可以像你一样只有一个字符串。需要记住的一件事是,如果适用,则为国际化。

现在在我的人身上我会有一个词典,这样你就可以在循环通过手机词典时将四个插入分成一个循环。如果您有账单或发货地址,我会使用simillar模型。

如果你不使用ORM,有一种方法可以帮助你使用sql params来干预DRY。以下代码不是为了编译而是为了向您展示再次最小化噪声的模式:

public class DALLayer
{
   public void InsertPerson(Person p)
   {
       using (SqlCommand sqlCmd=CreateNewCommand())
       {
           AddPersonParams(p,sqlCmd);
           sqlCmd.ExecuteNonQuery();
       }
   }

   public void UpdatePerson(Person p)
   {
       using (SqlCommand sqlCmd=CreateNewCommand())
       {
           AddPersonParams(p,sqlCmd);
           //We add the Id since we have it in updates but not in inserts
           sqlCmd.AddParameter("@PersonId",p.Id);
           sqlCmd.ExecuteNonQuery();
       }

   }

   private void AddPersonParams(Person p, Sqlcommand sqlCmd)
   {
       //Do all the code to add Params which exists in both insert and updates
   }

}

现在你已经完成的工作是合并的,所以当你向一个人添加一个新属性时,你只需要在处理参数时修改一个函数。

插入当前和以前的地址还有一件事,就是你没有干。你可以这样做:

private void InserAddress(Address address, int Id, AddressType addType)
{

}

现在,从插入Person例程中,您将调用此方法两次:

InsertAddress(p.CurrentAddress,id,CurrentAddress);
InsertAddress(p.FormerAddress,id,FormerAddress);

当然,如果你采纳我之前的建议,这可能看起来非常不同。

修改

我完全错过了这个,但我想强调一下克里斯所说的(我给你+1,但我觉得这是一件好事,我不得不重复它。使用属性: - )

答案 1 :(得分:2)

根据您列出的要求,您似乎不需要对应用程序中的数据进行太多操作。特别地,看起来这些中的一些可以被视为与用户相关联的数据列表,即名称,地址和电话的列表。您发布的数据访问代码似乎已经采用这种方式构建,我认为在您的方案中您不需要使应用程序的逻辑方面更加严格。

鉴于名称被视为与人员相关的数据列表,我认为您不希望第一次插入创建用户的部分。您可以将其他信息添加到主记录中,例如driversLicense,ssn,birthdate。

对于接口,请考虑您是否从中获取任何信息。这是打破类之间直接依赖关系的一种很好的方法,但它看起来并不是代码中的那种情况。另请注意,声明接口不会强制您使用get / set方法,因为您可以要求类具有get实现的属性。

为列表中使用的每个类添加一个type属性。您可以使用它来减少接口和数据访问层中的代码。在后面,您现在可以循环遍历列表并以相同的方式插入所有这些。

考虑使用可以帮助您进行数据访问的东西,比如linq2sql或nhibernate。这将简化数据访问代码并减少错误。

聚苯乙烯。对于所有场景都没有单一的解决方案,即使在特定情况下,个人体验也会影响每个人解决问题的方式。有些做法和原则旨在减少这种情况,但即使这样,也会出现差异。也就是说,我建议您阅读有关SOLID,DDD和TDD的一些信息。它们不是解决这些问题的方法,但了解这些问题肯定有助于软件开发。

更新:关于评论中的问题。 Linq2sql支持存储过程,在linq2sql上检查scott gu的系列:http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspx。你通过使用sp来放弃linq2sql的部分灵活性,但无论如何它都会对你有帮助。

关于更新。有不同的策略,主要问题是关于同一信息的并发更新。如果并发更新不是问题,那么您可以保留最新版本,这样您就可以保存数据。在这种情况下,您需要的唯一原始数据是记录的ID,您可以覆盖数据。如果需要检测并发更新,则必须保留所有原始值的副本或使用时间戳。更新记录时,sp代码需要检查原始值是否匹配。

您可以在设计器中配置linq2sql,以控制您使用的并发更新策略类型以及要发送的原始值。 SO中可能存在一些与此相关的问题/答案。你如何专门连接它,将取决于你给它的用途(使用它生成的实体或自己滚动,附加sp到实体或单独)甚至你使用的控件,因为其中一些可以保存原始值你(使用viewstate)。

答案 2 :(得分:1)

我注意到你使用ASP.NET,你应该知道会员提供商可以为你处理所有那些繁重的工作。

答案 3 :(得分:1)

我希望个人记录有子表的外键(姓名,地址,联系信息等)。

然后我有一个普通的旧对象,每个字段都有属性,还有一个存储库类,负责将类映射到数据库存储过程参数。

我没有填写所有的字段,但这里应该有足够的东西让你去。此外,您可以为每个类提取接口以进行编程(用于测试,模拟等)。

决定是否应该插入或更新保存将涉及编写udpate语句然后执行

public void Save()
{
    string.IsNullOrEmpty(Id) ? Insert() : Update();
}

清理数据类:

using System;
public class PersonName
{
    public string Id { get; set; }

    public string Last { get; set; }
    public string First{ get; set; }
    public string Middle{ get; set; }
    public string Suffix { get; set; }
}

public class PersonNameRepository
{
    public void Insert(PersonName pa)
    {
        SqlCommand cmDB = new SqlCommand("sp_InsertName", cnDB);
        cmDB.CommandType = CommandType.StoredProcedure;
        cmDB.Parameters.Add("@last_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@last_name"].Value = pa.Last;
        cmDB.Parameters.Add("@first_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@first_name"].Value = pa.First;
        cmDB.Parameters.Add("@middle_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@middle_name"].Value = pa.Middle;
        cmDB.Parameters.Add("@suffix_name", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@suffix_name"].Value = pa.Suffix;
        int id = cmDB.ExecuteNonQuery();
        pa.Id = id.ToString();
    }
}

public class PersonAddress
{
    public string Id { get; set; }

    public string Number { get; set; }
    public string Direction { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
}

public class PersonAddressRepository
{
    public void Insert(PersonAddress pa)
    {
        // Same as PersonNameRepository
    }
}


public class PersonInfo
{
    public string Id { get; set; }

    public DateTime BirthDate { get; set; }
    public string Gender { get; set; }
    public string SsNumber { get; set; }

}

public class PersonInfoRepository
{
    public void Insert(PersonInfo pa)
    {
        // Same as PersonNameRepository
    }
}
public class Person
{
    public string Id { get; set; }
    public PersonName CurrentName { get; set; }
    public PersonName FormerName { get; set; }

    public PersonAddress CurrentAddress { get; set; }
    public PersonAddress FormerAddress { get; set; }

    public PersonInfo Info { get; set; }
}

public class PersonRepository
{
    public void Insert(Person p)
    {
        // TODO: Begin Transaction

        p.CurrentName.Insert();
        p.FormerName.Insert();
        p.CurrentAddress.Insert();
        p.FormerAddress.Insert();
        p.Info.Insert();

        SqlCommand cmDB = new SqlCommand("sp_InsertPerson", cnDB);
        cmDB.CommandType = CommandType.StoredProcedure;
        cmDB.Parameters.Add("@current_name_id", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@current_name_id"].Value = p.CurrentName.Id;
        cmDB.Parameters.Add("@former_name_id", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@former_name_id"].Value = p.FormerName.Id; ;
        cmDB.Parameters.Add("@current_address_id", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@current_address_id"].Value = p.CurrentAddress.Id;
        cmDB.Parameters.Add("@former_address_id", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@former_address_id"].Value = p.FormerAddress.Id;
        cmDB.Parameters.Add("@info_id", System.Data.SqlDbType.VarChar, 50);
        cmDB.Parameters["@info_id"].Value = p.Info.Id;
        int id = cmDB.ExecuteNonQuery();
        pa.Id = id.ToString();

        // TODO: End Transaction
    }

}

答案 4 :(得分:0)

我很好奇你将如何处理人员地址的未来更新等。您可能想要考虑审计跟踪表,而不是将当前和以前的元素合并到一个对象中。让Person对象只包含一组数据。查询实际表中的当前数据,并针对先前和“上一个上一个”数据查询审计表。除非由于某些奇怪的原因,软件要求需要事先创建人名等等。

答案 5 :(得分:0)

很抱歉,我不会在这里为您提供完整的解决方案(只是想从此开始)。

我真的建议使用某种生成的数据访问层;例如。 Linq to SQL或NHibernate(还有更多,但这两个都很受欢迎)。您说难以维护的代码是您真正不应该维护的代码。让其他人在那里做咕噜咕噜的工作。

顺便说一句,我会说你正在做正确的事情,将所有数据分成实现接口的单独类。我会提到一件事 - 使用.Net你不需要明确的“getxxxx()”方法;使用带有公共getter的属性。它看起来像这样:

public class Name : IName
{
    private string _lastName;
    private string _firstName;
    private string _middleName;
    private string _suffixName;

    public string LastName { get { return _lastName; } }

    //Alternative automatic property:
    public string FirstName { get; protected set; } 
}

答案 6 :(得分:0)

一般来说,有很多好的答案可以展示不同的数据访问和业务逻辑层。我要补充的一件事就是为每一个类摆脱接口。当你确定知道只有一个实现它的类时,编写一个接口是过度设计的,并且不必要地使事情复杂化。现在,如果您正在编写一个类库,并且只提供一个类作为模板或其他人的起点,那么这将是不同的。但是这里显示的界面并没有为重新解释留下很大的空间。