使用相关代码表创建客户端实体

时间:2009-04-11 10:58:27

标签: entity-framework asynchronous

我正处于Silverlight路径的学习曲线上。我是一名以数据为中心的开发人员,因此我自然而然地选择了ADO.NET数据服务客户端。我在现实世界的场景中摸不着头脑,似乎无法在文档,博客等方面找到任何帮助。

我有一个复杂的Tutor实体,其中包含Addresses,PhoneNumbers和EmailAddresses的相关实体集。我还有其他一些如主题和证书。除此之外,还有用于查找表格的外键,例如StatusCodes,AddressTypes(如Home,Business等),EmailTypes等。所有这些都封装在我的Model项目中的edmx中。这是结构的一部分。

alt text

在Silverlight中,我有一个UserControl,它是这个导师的数据输入表单。我已经为数据绑定到客户端的TextBox控件创建了一个类似DTO的对象。一切顺利,直到用户点击“保存”。

Save例程创建并添加Tutor和Person对象,并将它们添加到DataServiceContext并正确链接它们。我遇到麻烦的地方是我必须在数据库的上下文中添加一个ALREADY存储的相关实体,例如代码表。

例如,该人可能有多个学科专业:小学数学,基础科学等.TutorSubjectSet必须与其他3个集合相关:主题(例如数学),主题级别(例如小学),然后是导师。我的DTO有一个组合的Subject_With_Level项目列表,它们提供了一个真正的笛卡尔选择的子集(至少不是我上学的地方,没有小学(学校)微积分这样的东西:-)。该列表显示为UI上的复选框列表。因此,当用户单击“保存”时,我会选中已检查的项目,然后尝试针对具有这些值的代码表对组合的Subject_With_Level.SubjectId和.SubjectLevelId值进行查找。

这是我迷失的地方。在服务器端功能中,我会没事的,因为我可以在线查找并立即获取实体。在异步情况下,如何在我忙于组装人物图表时获取相关实体?在“保存”过程中执行异步调用不起作用。

我尝试了各种各样的东西:我尝试使用Subject_With_Level.SubjectLevelId制作SubjectLevel的临时副本,并将其附加到上下文中,如下所示:




public static SubjectLevel MakeFakeSubjectLevelFor(TutoringEntities ctx, Subject_With_Level subjectAndLevel)
{
     var subjectLevel = new SubjectLevel()
                       {
                         SubjectLevelId = subjectAndLevel.SubjectLevelId,
                         Description = subjectAndLevel.SubjectLevel,
                         EffectiveDate = DateTime.Now,
                         EnteredBy = "",
                         EnteredDate = DateTime.Now,
                         Type = subjectAndLevel.SubjectLevel
                       }; 
    try { ctx.AttachTo("SubjectLevelSet", subjectLevel); }
    catch { //this tries to catch situations where the level (eg. Elementary) has already been created }
    return subjectLevel; 
} 



这种方法适用于没有重复的情况(它的优点是我不需要进行额外的调用。)例如在地址中,只有一个家庭地址(我有类似的功能) :MakeAFakeAddressTypeFor())。您会注意到我有一个try / catch,如果项目已插入SubjectLevelSet,则捕获错误。如果已插入该项并且我遇到该错误,则返回的subjectLevel不会附加到上下文。我收到错误,因为没有跟踪该项目。但是,我无法检索现有的subjectLevel而不对SubjectLevelSet发出Async查询,即使它位于我的本地上下文中。

我想做的是:


var lev = ctx.SubjectLevelSet.Where(l => l.SubjectLevelId == subjectAndLevel.SubjectLevelId).FirstOrDefault();
if(lev == null )
  lev = Helpers.MakeFakeSubjectLevelFor(ctx, subjectAndLevel);

但我得到:“不支持指定的方法”,我认为这意味着我必须执行查询异步,所以我回到了同样的情况。

我还尝试在Loaded事件委托中检索SubjectLevels列表。这样,当按下Save按钮时,我会有一组SubjectElements。同样的问题,我必须发出一个异步调用来进行搜索,即使我已经掌握了它。我尝试在列表中迭代我需要的那个但是这给了我一个错误,说明实体没有被上下文跟踪。

所以......显然我不理解这一点并且做错了但是我找不到任何做这种事情的实际例子。方法示例只是愉快地将基元加载到要存储的实体中。我见过的没有示例显示相关实体以及如何检索它们。我可以使它变得简单,只是存储codeId的整数值,而不是通过FK来关联它们,但这太过分了。

感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:0)

实际上我认为你觉得你必须进行查询异步,因为它需要太长时间?这个假设是否正确?如果是这种情况,您应该检查您尝试对查询本身执行的操作。我总是发现,如果我可以编写SQL来获得我想要的数据,那么我可以继续编写LINQ(使用LINQPad之类的东西)。

此外,您还可以创建一个“展平”复杂图形的SQL视图。然后在EF更新向导中确保选择视图。这样,每次构建此自定义复杂DTO时,您只需发出服务器端where子句,然后在那里填充值。

如果我在左侧领域外出让我知道,我在非常复杂的业务数据对象场景中拥有丰富的EF经验,而且我很可能错误地阅读了你的情况。

我认为SO上的人没有回答,因为它很冗长而且他们希望获得赏金,但只是猜测。