我一直在使用 WCF RIA 服务和 Silverlight,并在公开一项服务方面取得了一些成功,该服务提供从 ADO.NET 实体数据模型中获取的数据,该模型是从现有的 SQL Server 2008 Express 数据库建模的。数据库定义了表之间的许多关系,我希望能够使用客户端进行数据绑定(bind)。一切进展顺利,直到我尝试执行以下服务方法:public IQueryable<Timeline> GetHighlights() { var self = from x in Database.Timelines where User.Id == x.UserId || User.Id == x.SenderId select x; var friends = from x in Database.FriendItems where User.Id == x.UserId from y in Database.Timelines where x.FriendId == y.UserId || x.FriendId == y.SenderId select y; return self.Concat(friends).OrderByDescending(s => s.Id);}注意:'User' 是选择当前经过身份验证的用户的类的内部属性,而 Database 仅包装 ObjectContext 属性(为方便起见)。“Timeline”实体包含与“SilverfishUser”实体关联的 2 个导航属性“User”和“Sender”。当我遍历 'self' 查询的结果时,我看到前面提到的属性已经填充了当前用户(这是正确的)。但是,当我迭代“ friend ”查询的结果时,两个属性都为空(在序列化到客户端之前)。我试过设置:this.ContextOptions.LazyLoadingEnabled = false;//andthis.ContextOptions.ProxyCreationEnabled = false;而且我还尝试使用 Include 查询方法(启用和禁用延迟加载)来预先加载引用,但无济于事。我成功填充 Timeline 实体的 User 和 Sender 属性的唯一方法是使用以下语句:friends.ForEach(s => { if (!s.UserReference.IsLoaded) s.UserReference.Load(); if (!s.SenderReference.IsLoaded) s.SenderReference.Load();});据我了解,“加载”操作会导致在数据库上执行单独的查询。如您所见,当用户有许多 friend 并发布许多时间线帖子时,这可能会导致效率低下。我试图通过禁用延迟加载来避免的确切情况。我想将一个满载的实体返回给客户端,该实体可以绑定(bind)到尽可能少的查询。通过在域服务向导生成的元数据属性定义上应用 [Include] 属性,我已经克服了相关属性未序列化到客户端的问题。这个问题好像有点复杂,我试过的解决方案已经被别人广泛说了,理论上应该可以解决我的问题,但他们没有。同样,我能够成功填充实体的唯一方法是使用为关联属性创建的生成的 EntityReference 属性显式加载引用。任何有关此问题的帮助、经验或信息将不胜感激。[编辑] 当我执行这样的查询时,我的一些研究的更新: var friends = Database.FriendItems .Include("Friend.Timeline") .Where(s => User.Id == s.UserId);并访问导航属性(“friends.First().Friend.Timeline.First().User”)该值不为空。只有当我通过添加以下内容将时间线选择到新集合中时:.SelectMany(s => s.Friend.Timeline);导航属性不再具有任何值(value)。现在这只是一个猜测,但我只能假设它将属性值投影到一个新的对象实例中,因此它不会重新填充这些属性以避免循环引用?无论如何,这是一个很难解决的问题。希望有人比我更了解这一点。 最佳答案 好吧,我设法找到了一些解决方法,尽管不是一个非常优雅的方法。我会将其发布为答案,以便人们可以查看它,但如果可能的话,我将让问题保持开放并归功于更合适的解决方案。这是我的修复:public IQueryable<Timeline> GetHighlights() { var self = from x in Database.Timelines where User.Id == x.UserId || User.Id == x.SenderId select x; var friends = from x in Database.FriendItems.Include("Friend.Timeline") where (User.Id == x.UserId) select x.Friend.Timeline; List<Timeline> highlights = new List<Timeline>(); highlights.AddRange(self); friends.ForEach(x => x.ForEach(y => highlights.Add(y))); return highlights.AsQueryable().OrderByDescending(s => s.Id);}我 认为 这样做的原因是通过手动创建新集合,我防止将实体投影到新对象中,从而保留加载的关系属性。同样,这只是猜测,但假设遵循了一个很好的模式,哈哈。关于sql - 禁用延迟加载和急切加载实体引用未按预期工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7617253/
10-11 02:08