Как я могу использовать LazyLoading с WCF, не вызывая циклические ссылки? - PullRequest
1 голос
/ 21 марта 2011

Я выполняю проверку с использованием атрибутов DataAnnotation в классах Model, а класс Model используется для проверки как на стороне клиента, так и на стороне приложения.

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

Используются следующие библиотеки:

  • Сервисная библиотека WCF
  • Клиентская библиотека DataAccess
  • Библиотека моделей

Поскольку библиотека моделей используется как на стороне клиента, так и на стороне сервера для проверки данных, я не могу ссылаться на библиотеку DataAccess из библиотеки моделей. Следовательно, как я могу настроить отложенную загрузку?

Например, у меня есть ConsumerModel, у которого есть свойство PhoneNumbers, которое должно загружаться лениво. Как я могу загрузить PhoneNumberModels из ConsumerModel, не ссылаясь на DAL на стороне клиента?

DAL на стороне клиента:

using MyModels;

public class ConsumerDataAccess
{
    public ConsumerModel GetConsumerById(int id)
    {
        ConsumerDTO dto = WCFService.GetConsumer(id);
        return new ConsumerModel(dto);
    }
}

ConsumerModel:

public class ConsumerModel
{
    public ObservableCollection<PhoneNumberModel> _phoneNumbers;

    public ObservableCollection<PhoneNumberModel> PhoneNumbers
    {
        get
        {
            if (_phoneNumbers == null)
            {
                // Can't reference DataAccess Library since that would cause a Circular Reference
            }
        }
    }
}

Какими альтернативными способами я мог бы заставить эту архитектуру работать?

Я бы предпочел сохранить Валидацию с Моделями и использовать модели как со стороны Клиента, так и со стороны Сервера для проверки. Я также предпочел бы продолжать использовать DataAnnotation для проверки.

EDIT

Вот мое окончательное решение, основанное на ответе Лоуренса Уэнама, если кому-то интересно. Я закончил тем, что использовал делегат вместо события.

DAL:

public class ConsumerDataAccess
{
    public ConsumerModel GetConsumerById(int id)
    {
        ConsumerDTO dto = WCFService.GetConsumer(id);
        ConsumerModel rtnValue = new ConsumerModel(dto);
        ConsumerModel.LazyLoadData = LazyLoadConsumerData;
        return rtnValue;
    }
}

private object LazyLoadConsumerData(string key, object args)
{
    switch (key)
    {
        case "Phones":
            return PhoneDataAccess.GetByConsumerId((int)args);
        default:
            return null;
    }
}

Библиотека моделей:

public class ConsumerModel
{
    public delegate object LazyLoadDataDelegate(string id, object args);
    public LazyLoadDataDelegate LazyLoadData { get; set; }

    public ObservableCollection<PhoneNumberModel> _phoneNumbers;

    public ObservableCollection<PhoneNumberModel> PhoneNumbers
    {
        get
        {
            if (_phoneNumbers == null && LazyLoadData != null)
            {
                _phoneNumbers = (ObservableCollection<PhoneNumberModel>)
                        LazyLoadData("Phones", ConsumerId);
            }
            return _phoneNumbers;
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 21 марта 2011

Одним из способов может быть вызов события в get {} свойств ваших классов модели, а затем реализация менеджера отложенной загрузки на стороне клиента, имеющего ссылку на ваш DAL.EG:

public class LazyLoadEventArgs: EventArgs
{
    public object Data { get; set; }

    public string PropertyName { get; set; }

    public int Key { get; set; }
}

Затем в ваших классах Model:

public event EventHandler<LazyLoadEventArgs> LazyLoadData;

public ObservableCollection<PhoneNumberModel> PhoneNumbers
{
    get
    {
        if (_phoneNumbers == null)
        {
            LazyLoadEventArgs args = new LazyLoadEventArgs {
                PropertyName = "PhoneNumbers",
                Key = this.Id
            };
            LazyLoadData(this, args);
            if (args.Data != null)
               this._phoneNumbers = args.Data as ObservableCollection<PhoneNumberModel>;
        }
        return _phoneNumbers;
    }
}

Обработчик события LazyLoadData будет выполнять выборку данных из DAL на стороне клиента, а затем сохранять их в.Data свойство LazyLoadEventArgs.EG:

private void Model_HandleLazyLoadData(object sender, LazyLoadEventArgs e)
{
    switch (e.PropertyName)
    {
        case "PhoneNumbers":
            e.Data = DAL.LoadPhoneNumbers(e.Key);
            break;
        ...
    }
}
0 голосов
/ 21 марта 2011

Не используйте «ленивую загрузку» с WCF.Сетевое общение стоит времени.Если вы планируете использовать PhoneNumbers, ваша служба должна предоставить метод, который вернет Customer с номерами телефонов.Другой подход заключается в использовании WCF Data Services , который предлагает запросы linq на стороне клиента с возможностью определения активной загрузки с помощью метода Expand.

Вы должны уменьшить количество вызовов службы до минимума.

После прочтения вашего вопроса я не понимаю, почему вы делитесь моделью между сервисом и клиентом.Модель - это особенность клиента.Единственная общая часть должна быть DTO.

...