Нужна помощь в дизайне класса - PullRequest
1 голос
/ 19 января 2009

Я новичок в программировании, поэтому я подумал, что смогу получить помощь от тех, кто знает это.

В настоящее время я пишу регистрационное приложение, которое в основном будет принимать данные от пользователей, проверяет введенные данные, отображает экран просмотра (который пользователь должен распечатать и отправить по почте в копии), а затем сохраняет введенную информацию в базу данных.

Вот поля, которые нужно захватить и сохранить.

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 или интерфейс для классов. т.е. * +1008 *

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;
}

Edit: я чувствую, что этот код будет чрезвычайно сложно поддерживать позже. Может кто-нибудь помочь мне найти более простой / поддерживаемый способ сделать это? Я также озадачен тем, как мне следует обновить запись после ее добавления.

Заранее спасибо за любую помощь

Ответы [ 7 ]

3 голосов
/ 25 марта 2009

Во-первых, если вы хотите упростить обслуживание, я бы посмотрел на использование 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
}

Некоторые люди могут указывать в Phone числовые значения, поэтому я не хочу это обсуждать, или вы можете просто указать одну строку, как вы. Следует иметь в виду одну вещь - интернайтонализация, если это применимо.

Теперь, на моем лице, у меня будет словарь, который позволит вам затем разбить четыре вставки в один цикл, когда вы перебираете словарь телефона. Я бы использовал модель симларла, если у вас есть биллинг или корабль по адресу.

Если вы не используете ORM, один из способов помочь DRY с вашими параметрами sql прост. Следующий код предназначен не для компиляции, а просто для того, чтобы показать вам шаблон, чтобы снова минимизировать шум:

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 тебе, но я чувствовал, что это было так хорошо, что мне пришлось это повторить. Используйте Свойства: -)

2 голосов
/ 24 марта 2009

Исходя из перечисленных вами требований, вам не нужно много манипулировать данными в приложении. В частности, похоже, что некоторые из них могут рассматриваться как списки данных, связанных с пользователем, то есть списки имен, адресов и телефонов. Код доступа к данным, который вы разместили, кажется, структурирован таким образом, я не думаю, что в вашем сценарии у вас есть необходимость сделать логическую сторону вашего приложения более жесткой.

Учитывая имена обрабатываются как список данных, связанных с человеком, я не думаю, что вы хотите сделать первую вставку этого элемента, который создает пользователя. У вас есть другая информация, которую вы можете добавить в основную запись, например driversLicense, ssn, дата рождения.

Для интерфейсов подумайте, получаете ли вы их. Это хороший способ разорвать прямые зависимости между классами, но не похоже, что у вас есть такой сценарий в коде. Также обратите внимание, что объявление интерфейсов не заставляет вас использовать метод get / set, так как вы можете требовать, чтобы свойство с get было реализовано классом.

Добавить свойство типа для каждого из классов, используемых в списках. Вы можете использовать это для уменьшения кода как на уровне интерфейса, так и на уровне доступа к данным. В последующем вы теперь можете просто пройтись по списку и вставить все их одинаково.

Попробуйте использовать что-то, что поможет вам с доступом к данным, например linq2sql или nhibernate. Это упростит код доступа к данным и сделает его менее подверженным ошибкам.

Ps. не существует единого решения для всех сценариев, и даже в конкретных сценариях личный опыт будет влиять на то, как каждый человек решает проблему. Существуют практики и принципы, призванные уменьшить это, но даже тогда появляются различия. Тем не менее, я предлагаю вам прочитать некоторую информацию о SOLID, DDD и TDD. Они не являются рецептом для решения этих проблем, но знание о них определенно помогает разработке программного обеспечения.

Обновление: О вопросах в комментариях. Linq2sql поддерживает хранимые процедуры, проверьте серию scott gu на linq2sql: 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. Вы теряете часть гибкости linq2sql, используя sp, но это все равно вам поможет.

По поводу обновлений. Существуют разные стратегии, основная проблема заключается в одновременном обновлении одной и той же информации. Если одновременные обновления не являются проблемой, тогда вы можете просто оставить последнюю версию и сохранить данные. В этом случае единственными исходными данными, которые вам нужны, является идентификатор записи, и вы позволяете перезаписывать данные. Если вам нужно обнаружить параллельные обновления, вам нужно либо сохранить копию всех исходных значений, либо использовать временную метку. При обновлении записи sp-код должен проверять соответствие исходных значений.

Вы можете настроить linq2sql в конструкторе, чтобы контролировать, какой тип стратегии обновления параллелизма вы используете и какие исходные значения вы отправляете. Вероятно, есть некоторые вопросы / ответы в SO, связанные с этим. То, как вы его конкретно подключите, будет зависеть от того, как вы его используете (используя созданные им объекты или сворачиваете свои собственные, присоединяете sp к объектам или по отдельности) и даже от используемых вами элементов управления, поскольку некоторые из них могут содержать исходные значения вы (используя viewstate).

1 голос
/ 25 марта 2009

Я бы хотел, чтобы запись о человеке имела внешние ключи для вложенных таблиц (имена, адреса, контактные данные и т. Д.).

Затем у меня есть простой старый объект со свойствами для каждого поля и класс репозитория, который отвечает за отображение класса в параметры хранимой процедуры базы данных.

Я не заполнил все поля, но здесь должно быть достаточно, чтобы вы начали. Кроме того, вы можете извлекать интерфейсы для каждого класса для программирования (для тестирования, насмешек и т. Д.).

Чтобы решить, нужно ли сохранять или обновлять сохранение, нужно написать операторы 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
    }

}
1 голос
/ 19 января 2009

Я заметил, что вы используете ASP.NET, вы должны знать, что поставщик членства может справиться со всей этой тяжелой работой за вас.

0 голосов
/ 27 марта 2009

В общем, есть много хороших ответов, которые демонстрируют различные уровни доступа к данным и бизнес-логики. Вдобавок ко всему, я бы добавил избавление от интерфейсов для каждого отдельного класса. Написание интерфейса, когда вы точно знаете, что когда-либо будет только один класс, реализующий его, является чрезмерным дизайном и излишне усложняет вещи. Теперь, если вы писали библиотеку классов и предлагали только один класс в качестве шаблона или отправной точки для других, то это было бы иначе. Но представленные здесь интерфейсы не оставляли много места для повторной интерпретации.

0 голосов
/ 25 марта 2009

Извините, я не собираюсь предлагать вам полное решение (просто хотел бы начать с этого).

Я бы действительно рекомендовал использовать какой-то сгенерированный уровень доступа к данным; например. Linq to SQL или NHibernate (их больше, но оба они довольно популярны). Код, который вы говорите, что вам будет трудно поддерживать, это код, который вам действительно не нужно поддерживать. Пусть кто-нибудь другой выполнит там тяжелую работу.

В качестве отступления я бы сказал, что вы поступаете правильно, разделяя все данные на отдельные классы, реализующие интерфейсы. Хотя я упомяну одну вещь: с .Net вам не нужно создавать явные методы "getxxxx ()"; Используйте собственность с публичным добытчиком. Это будет выглядеть примерно так:

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; } 
}
0 голосов
/ 24 марта 2009

Мне любопытно, как вы будете обрабатывать будущие обновления адреса человека и т. Д. Вместо объединения текущих и предыдущих элементов в один объект вы можете рассмотреть таблицу контрольного журнала. Пусть ваш объект Person содержит только один набор данных. Запрос фактической таблицы для текущих данных и запрос к таблице аудита для предыдущих и «предыдущих-предыдущих» данных. Если, по какой-то странной причине, требования к программному обеспечению не требуют предварительного имени и т. Д., Заранее при создании человека.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...