【问题标题】:CommunicationException when I call WCF from Silverlight (or how to get ALL data from DB in one function)当我从 Silverlight 调用 WCF 时发生 CommunicationException(或如何在一个函数中从 DB 获取所有数据)
【发布时间】:2014-01-07 12:12:20
【问题描述】:

我有一个关于使用 Liqn to SQL 处理 DB 的问题。

我有一个小数据库,其中包括 4 个表,并且我为这些表创建了 Liq to SQL 类: 所以,这一切都是在我的 AppName.Web 项目上创建的。我还创建了一个 WPF 服务,它返回包含所有条目的列表集合。 当我试图从 Silverlight 项目中调用我的函数时,我得到了 CommunicationException。我尝试设置maxReceivedMessageSize 和maxBufferSize,但问题仍然出现。比我添加[DataContract] 和[DataMember] 标记到自动生成的类(属性除外,它表示引用,如Mod 表中的Items,Recipes 和Item 表中的Entries 等)它开始工作,但我只能从一个表中接收数据。

如何接收所有表格中包含所有子项的 Mod 列表? linq to sql 是最好和最简单的方法之一吗?

UPD1: 返回列表的函数:

public MCDataClassesDataContext GetContext()
{
    var context = new MCDataClassesDataContext();
    var dlo = new DataLoadOptions();
    dlo.LoadWith<Mod>(p => p.Item);
    dlo.LoadWith<Item>(p => p.Recipe);
    dlo.LoadWith<Item>(p => p.Entry);
    dlo.LoadWith<Recipe>(p => p.Entry);
    context.LoadOptions = dlo;
    return context;
}

public List<Mod> GetMods()
{
    return GetContext().Mod.ToList();
}

【问题讨论】:

  • 问题是你的代码没有很好的分层。 WCF 服务应该位于与数据访问层分开的中间层。并且 UI 应该与中间层分开。
  • 在创建 SL 应用程序时,您有 2 个项目:一个用于数据和服务,一个用于 UI。我试图从 AppName.Web 获取数据到 AppName 项目(就像在所有 SL 项目中一样)

标签: c# wcf silverlight


【解决方案1】:

CommunicationException 异常广泛。您能否在 WCF 服务上创建一个简单的操作以确保其可访问并且您没有配置/托管问题?

或者打开 WCF 消息日志记录并使用 svctraceviewer 更好地了解 CommunicationException (http://msdn.microsoft.com/en-us/library/ms730064(v=vs.110).aspx) 的根本原因

还要确保在从 WCF 服务返回之前实现 Linq2Sql 查询的结果。

关于对象关系映射器 (ORM) 的选择,不推荐使用 Linq2Sql,而支持 EntityFramework。它仍然有效,但就像人类的阑尾一样,它是进化的死胡同。


查看堆栈跟踪后,我能够确定 WCF 无法序列化相关类型,因为 Linq2Sql 将它们作为动态代理而不是作为您已标记为数据协定的类型发出。我建议在从您的服务返回之前手动或使用具有类似效果的 Automapper 进行映射 Select(i => new Mod() { Items = i.Items.Select((j) => new Item() { Foo = j.Foo } } });

等等

另一个注意事项:EntityFramework 允许关闭动态代理的选项,但我不知道 Linq2Sql 是否这样做。 (作为两者的比较点)

【讨论】:

  • 就像我之前说的,我创建了一个函数来获取没有任何关系的 Mod 列表(没有 Items 字段)并且效果很好。
  • 我尝试使用 ADO.NET EDM,但收到了同样的错误。在调试模式下,我可以看到我的服务函数返回什么,但我无法在客户端上接收它。此处出现错误:服务参考文件中的ObservableCollection&lt;Mod&gt; _result = ((ObservableCollection&lt;Mod&gt;)(base.EndInvoke("GetMods", _args, result)));。
  • 由于问题出在相关集合上,我仍然认为这是一个物化问题。如果您使用 DataLoadOption (stackoverflow.com/questions/5783109/…) 通过初始查询加载相关集,它是否有效?
  • 在调试模式下,我会看到函数返回什么。这就是我想要的一切(所有mods 以及所有相关数据)。我将尝试 DataLoadOption 并在此处发表评论。
  • 我尝试使用DataLoadOption,但问题仍然出现。你说的将结果实体化是什么意思?我将我的函数添加到正文中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
  • 2015-07-29
  • 2019-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多