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

Entity framework 使用相关代码表创建客户端实体,entity-framework,asynchronous,Entity Framework,Asynchronous,我正沿着Silverlight小径学习。我是一名以数据为中心的开发人员,因此我很自然地选择了ADO.NET数据服务客户端。我对一个真实的场景摸不着头脑,似乎在文档、博客等方面找不到任何帮助 我有一个复杂的导师实体,包含地址、电话号码和电子邮件地址的相关实体集。我还有其他几套,比如科目和证书。与所有这些一起出现的还有外键,用于查找表中的状态码、地址类型(如家庭、业务等)、电子邮件类型等。所有这些都封装在我的模型项目中的edmx中。这是结构的一部分 在Silverlight中,我有一个UserCo

我正沿着Silverlight小径学习。我是一名以数据为中心的开发人员,因此我很自然地选择了ADO.NET数据服务客户端。我对一个真实的场景摸不着头脑,似乎在文档、博客等方面找不到任何帮助

我有一个复杂的导师实体,包含地址、电话号码和电子邮件地址的相关实体集。我还有其他几套,比如科目和证书。与所有这些一起出现的还有外键,用于查找表中的状态码、地址类型(如家庭、业务等)、电子邮件类型等。所有这些都封装在我的模型项目中的edmx中。这是结构的一部分

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

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

例如,此人可能有多个学科专业:基础数学、基础科学等。导师科目集必须与其他3个科目集相关联:科目(如数学)、科目级别(如基础),然后是导师。我的DTO有一个由科目和水平项目组合而成的列表,显示了真正笛卡尔选择的子集(没有小学(学校)微积分,至少我在哪里上学:-)。该列表在UI上显示为复选框列表。因此,当用户单击“保存”时,我会选择选中的项,并尝试根据具有这些值的代码表,查找带有_Level.SubjectId和.SubjectLevelId的组合主题_

这就是我迷路的地方。在服务器端函数中,我可以这样做,因为我可以在线查找并立即获取实体。在异步情况下,当我忙于组装人形图时,如何获取相关实体?在保存过程中间执行异步调用无效。

我尝试了各种方法:我尝试使用Subject_和_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不会附加到上下文。我收到一个错误,因为没有跟踪该项目。但是,如果不对SubjectLevelSet发出异步查询,则无法检索现有subjectLevel,即使它在本地上下文中也是如此

我想做的是:


var lev = ctx.SubjectLevelSet.Where(l => l.SubjectLevelId == subjectAndLevel.SubjectLevelId).FirstOrDefault();
if(lev == null )
  lev = Helpers.MakeFakeSubjectLevelFor(ctx, subjectAndLevel);
但是我得到:“不支持指定的方法”,我假设这意味着我必须异步执行查询,所以我又回到了同样的情况

我还尝试在加载的事件委托中检索SubjectLevel列表。这样,当按下Save按钮时,我手头就有一组SubjectElements。同样的问题,我必须发出一个异步调用来进行搜索,即使我手头有它。我尝试在列表中迭代我需要的那个,但这给了我一个错误,即上下文没有跟踪实体

所以…很明显,我不理解这一点,我做错了,但我找不到任何实际的例子来做这种事情。how-to示例只是愉快地将原语加载到要存储的实体中。我没有看到任何示例显示相关实体以及如何检索它们。我可以让它变得简单,只存储codeId的整数值,而不通过FK将它们关联起来,但这太折衷了


感谢您能为我提供的任何帮助。

现实地说,我认为您觉得必须异步执行查询,因为它需要太长时间?这个假设正确吗?如果是这样的话,您应该检查您试图对查询本身做什么。我总是发现,如果我可以编写SQL以获得我想要的数据,那么我就可以继续向它写入LINQ(使用类似LINQPad的东西)

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

如果我是左图中的一员,请告诉我,我在非常复杂的业务数据对象场景中有丰富的EF经验,我很可能错误地理解了您的情况

我认为,SO上的人没有回答,因为它太长了,他们希望得到赏金,不过这只是一个猜测