#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. Не повезло, все еще получаю эту ошибку: сервер не предоставил значимого ответа; это может быть вызвано несоответствием контракта, преждевременным завершением сеанса или внутренней ошибкой сервера.