WCF с первой связью кода Entity Framework

#wcf #entity-framework

#wcf #entity-framework

Вопрос:

Я изучаю WCF и попытался создать небольшой сервис, который предоставляет проект и его задачи (стандартная Entity Framework hello world).

Структура класса следующая:

 public class Project
{
    public int ProjectId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime CreationDate { get; set; }
    public virtual ICollection<Task> Tasks { get; set; }
}

public class Task
{
    public int TaskId { get; set; }
    public string Title { get; set; }
    public virtual Project RelatedProject { get; set; }
}
 

Контекст БД появляется после:

 public class ProjectContext : DbContext
{
    public DbSet<Project> Projects { get; set; }
    public DbSet<Task> Tasks { get; set; }
}
 

Наконец, конечная точка службы:

     public IEnumerable<Project> getProjects()
    {
        ProjectContext p = new ProjectContext();
        return p.Projects.AsEnumerable();
    }
 

Проблема в том, что эта модель приведет к сбою системы.ServiceModel.Исключение CommunicationException, но, если я удалю виртуальные свойства из модели, это сработает, но я потеряю связи entity Framework между проектом и задачей.

У кого-нибудь есть похожие настройки?

Комментарии:

1. Работает ли это, если вы включаете Tasks ? return p.Projects.Include(p => p.Tasks).AsEnumerable();

2. Это даже не будет компилироваться, но я вижу идею, я буду следовать этому варианту 😉

3. Хм, не пробовал (очевидно), но обнаружил, что на ADO.NET Блог команды :

Ответ №1:

Я несколько часов бился головой об стену с этим. После обширной отладки Google дал ответ, и я чувствую себя вправе опубликовать его здесь, поскольку это был первый результат, который я получил в Google.

Добавьте этот класс поверх [ServiceContract] объявления вашего интерфейса (обычно IProjectService.cs

 public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
    {

    }

    public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
    {
        var dataContractSerializerOperationBehavior =
            description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver =
            new ProxyDataContractResolver();
    }

    public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
    {
        var dataContractSerializerOperationBehavior =
            description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver =
            new ProxyDataContractResolver();
    }

    public void Validate(OperationDescription description)
    {
        // Do validation.
    }
}
 

Требования следующие

 using System.ServiceModel.Description;
using System.Data.Objects;
using System.ServiceModel.Channels;
 

Затем под [OperationContract] ключевым словом добавьте [ApplyDataContractResolver] ключевое слово, и все готово!

Большое спасибо http://blog.rsuter.com/?p=286

Ответ №2:

Для отправки данных через WCF вы должны отключить отложенную загрузку ( dataContext.ContextOptions.LazyLoadingEnabled = false; ).

Чтобы быть уверенным, что нужные вам данные загружены, вам нужно использовать быструю загрузку (через метод Include).

Вам нужно изменить свою функцию на:

  public IEnumerable<Project> getProjects()
    {
        ProjectContext p = new ProjectContext();
        p.ContextOptions.LazyLoadingEnabled = false;

        return p.Projects.Include("Tasks").AsEnumerable();
    }
 

Комментарии:

1. Не повезло, все еще получаю эту ошибку: сервер не предоставил значимого ответа; это может быть вызвано несоответствием контракта, преждевременным завершением сеанса или внутренней ошибкой сервера.