Дилемма бизнес-объекта C # CSLA: только чтение против чтения / записи

Я являюсь частью команды, которой поручено обновить наше старое приложение базы данных VB6 UI / COBOL до современных времен. Перед тем, как меня наняли, было принято решение (я уверен, в основном, из-за продаж) переделать пользовательский интерфейс перед базой данных. Итак, теперь мы используем WPF и MVVM с большим эффектом, до сих пор это было потрясающе, особенно использование CSLA в качестве нашего уровня модели.

Однако, поскольку наша разработка ведется параллельно со следующей версией старого продукта, мы немного ограничены. Мы не можем вносить какие-либо изменения (или минимальные изменения) в вызовы, сделанные в базе данных COBOL. До сих пор это было хорошо, хотя, если вы можете в это поверить, возвращаетесь к временам славы SQL Server.

Там, где я столкнулся с особенно неприятным препятствием в отношении нашего дизайна BO, является работа с «легкими» бизнес-объектами, возвращаемыми в списках, и их «полными» аналогами. Позвольте мне попытаться построить пример:

Допустим, у нас есть объект person в БД с кучей полей. Когда мы выполняем поиск в этой таблице, мы не возвращаем все поля, поэтому мы заполняем ими наш облегченный объект. Эти поля могут быть или не быть подмножеством полного человека. Возможно, мы сделали соединение или два, чтобы получить некоторую другую информацию, специфичную для поиска. Но если мы хотим отредактировать наш объект person, мы должны сделать еще один вызов, чтобы получить полную версию для заполнения пользовательского интерфейса. В результате у нас остается два объекта и мы пытаемся манипулировать их состоянием в одной виртуальной машине, все время пытаясь сохранить синхронизацию списка людей на любом родительском объекте, который он находится после удаления, редактирования и добавления. Изначально я сделал наш объект lite person производным от ReadOnlyBase ‹>. Но теперь, когда я имею дело с тем же поведением списка, что и со списком полных BO, за исключением наполовину заполненных, наполовину облегченных, я думаю, мне следовало просто сделать как облегченную, так и полную версии производными от BusinessBase ‹ > и просто сделал свойства установщика облегченной версии закрытыми.

Кто-нибудь еще сталкивался и нашел решение для этого? Выспавшись на нем, я придумал это потенциальное решение. Что, если мы заключим полную и облегченную версию нашего BO в другой BO, например:

public class PersonFull : BusinessBase<PersonFull>
{
  ...
}
public class PersonLite : BusinessBase<PersonLite>
{
  ...
}

public class Person : BusinessBase<Person>
{
  public PersonFull PersonFull;
  public PersonLite PersonLite;
}
public class PersonList : BusinessListBase<PersonList, Person>
{
}

Очевидно, все будет зарегистрировано CSLA собственности и тому подобное, но для краткости они поля там. В этом случае Person и PersonList будут содержать все фабричные методы. После операции поиска PersonList будет заполнен объектами Person, все члены PersonLite которых были заполнены, а объекты PersonFull были пустыми. Если нам нужно получить полную версию, мы просто говорим об этом объекту Person, и теперь у нас есть объект PersonFull, чтобы мы могли заполнить пользовательский интерфейс редактирования. Если объект Person должен быть удален, мы можем легко сделать это с помощью процедур удаления CSLA, сохраняя при этом целостность наших списков на всех виртуальных машинах, которые его слушают.

Итак, я надеюсь, что это имело смысл для всех, и если у кого-то есть другое решение, которое они успешно использовали, или критикуют это, во что бы то ни стало!

Спасибо!

(Перепечатано с: http://forums.lhotka.net/forums/thread/35576.aspx)


person opedog    schedule 14.08.2009    source источник


Ответы (2)


public class PersonLite : ReadOnlyBase<PersonLite>
{
    public void Update(PersonFull person) { }
}

public class PersonFull : BusinessBase<PersonFull>
{
    // blah blah
}

Я бы обновил "облегченный" объект изменениями, внесенными в "полный" объект, и оставил бы его как ReadOnlyBase. Важно помнить, что «ReadOnly» в ReadOnlyBase означает объект, который только читается из базы данных и никогда не сохраняется в ней. Менее элегантное, но более точное имя было бы NotSavableBase, потому что таким объектам не хватает DataPortal_XYZ механизмов для чего угодно, кроме выборки. По понятным причинам такие объекты обычно имеют неизменяемые свойства, но это не обязательно. ReadOnlyBase происходит от Core.BindableBase и реализует INotifyPropertyChanged, поэтому изменение значений его свойств будет нормально работать с привязкой.

Когда вы сохраняете свой «полный» объект, вы передаете только что сохраненный экземпляр методу Update(PersonFull) экземпляра, который находится в вашем списке, и обновляете свойства «облегченного» объекта из «полного» объекта.

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

person Gregory Higley    schedule 16.08.2009

Если вы посмотрите примеры Рокки, которые поставляются с фреймворком CSLA, вы заметите, что он всегда отделяет объекты только для чтения от объектов для чтения / записи. Я думаю, что это сделано не зря, потому что поведение будет кардинально отличаться. Объекты, доступные только для чтения, будут в большей степени ориентированы на производительность, их проверка будет сильно отличаться и, как правило, в целом будет меньше информации. Объекты чтения / записи не будут основаны на производительности и будут в значительной степени зависеть от проверки, авторизации и т. Д.

Однако это оставляет вас перед дилеммой, в которой вы сейчас оказались. Я бы перегрузил конструктор каждого класса, чтобы вы могли передавать их друг в друга и «копировать» то, что вам нужно, друг из друга.

Что-то вроде этого:

public class PersonLite : BusinessBase<PersonLite>
{
    public PersonLite(PersonFull fullPerson)
    {
        //copy from fullPerson's properties or whatever
    }
}

public class PersonFull : BusinessBase<PersonFull>
{
    public PersonFull(PersonLite litePerson)
    {
        //copy from litePerson's properties or whatever
    }
}

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

person Joseph    schedule 14.08.2009
comment
Я не совсем уверен, что то, что вы предлагаете, должно решить. Облегченный БО никогда не будет заполнять полный БО, так как мы можем просто перейти к БД, чтобы заполнить полный БО уникальными данными из облегченной версии. Думаю, я мог бы увидеть полную версию, обновляющую облегченную версию после редактирования, но на самом деле это не способ сделать это. - person opedog; 14.08.2009
comment
Облегченная версия не сможет полностью заполнить полную версию, но этого может быть достаточно, чтобы ее можно было отобразить для пользователя, а оставшиеся данные можно было бы отложить. Раньше я делал это с некоторым успехом. Если вы пытаетесь изменить объекты памяти, то ваш подход к этому будет совершенно другим. - person Joseph; 14.08.2009
comment
Если намерение состоит в том, чтобы перестроить внутренние BO теперь, когда интерфейс завершен, почему бы не использовать это в качестве тестового примера для начала с новыми объектами CSLA, которые содержат все свойства? - person Mark Redman; 14.08.2009
comment
Хороший вопрос. В настоящее время наши BO сопоставляются непосредственно с макетами файловых записей в COBOL, и я помещаю атрибуты в свойства, чтобы вспомогательный класс знал, как анализировать входные данные из COBOL и заполнять свойства. Вот почему у нас есть 2 разных объекта, потому что у нас есть 2 разных макета записей, которые поступают из БД. И эта разработка происходит одновременно с фронтенд-разработкой. - person opedog; 14.08.2009
comment
Это не то, как работает Csla, и вы бы не подошли к проблеме таким образом. - person Andy; 18.04.2011