2011-02-12 45 views
10

如果模型打到相同的底层数据库,是否有方法可以组合来自2个不同实体模型的查询?我有一个使用EF进行数据访问的框架(EDM 1) 我有一个客户端应用程序,它使用框架的服务并且还使用EF作为自己的数据访问。 EDM2)跨实体数据模型撰写查询

有些情况下,我需要编写查询并加入跨2个EDM的实体。

有没有办法做到这一点,而不从第一个EDM获取内存中的数据,然后在第二个EDM的实体内存中应用额外的谓词/连接?

我希望我这阐明正确的方式

编辑 @Ladislav Mrnka: 第EDM是一个可重用的框架数据访问层。 把EF生成的实体与这个EDM相结合是没有意义的 那些消费客户端 它击败了API的可重用性,如果我这样做,我不得不随身携带附加的膨胀 (EF元数据和数据库每次我想重新部署框架时,客户端的表)。此外,这也会使设计师在管理模型时变得笨拙。

我目前使用的是什么你提到序号项目7作为solutuon和表现糟糕的 由于这样的事实,我要结束返回比使用 EDM1然后框架需要更多的数据(即实体)基于来自第二EDM中实体的 属性的值,根据谓词/条件过滤掉不需要的谓词/条件。最终结果是巨大的性能下降和不愉快的DBA。

出于这个原因我最终推动检索实体 在其中我可以访问两个电火花使用的表和申请所需 谓词和对整个查询运行在一个数据库中的存储过程所需的逻辑,而不是以使内存 的数据,然后过滤掉不必要的ones.Downside的是,我不能使用LINQ

项目你提到听起来很有趣,但是从8这听起来像我怀疑 你在设计强类型时间,还是你? 你可以上传你的代码样本吗?我可以试试吗?

+0

难道你不能在后端执行此操作,或者sql数据库目录是否可以通过链接服务器或同等服务器查看对方? – CarneyCode 2011-02-13 10:07:00

+0

@ Carnotaurus:这就是我目前正在做的事情。两个EDM的表格都在同一个数据库中,因此我使用Sproc来查询框架表格(EDM1)和客户端表格(EDM2)。缺点是我不能使用LINQ – 2011-02-13 23:28:57

回答

4

重要编辑

有在两个ObjectContext类型实现这一目标的支持没有建立。您的查询必须始终针对单个ObjectContext执行。

可能是最好的去路:这对我来说自己尝试一下很有趣。我从非常简单的想法开始。两个EDMX文件(与POCO T4生成器一起使用),每个包含一个实体。我从第二个连接字符串获取元数据描述并将其添加到第一个连接字符串。我直接使用ObjectContextObjectSet。通过这样做,我能够从单个ObjectContext实例查询和修改两个实体。我也尝试从这两个模型创建查询连接实体,它工作。 只有当两个EDMX映射到相同的数据库(相同的数据库连接字符串)时,这显然才起作用。

的重要组成部分,是连接字符串:

<configuration> 
    <connectionStrings> 
    <add name="TestEntities" connectionString="metadata=res://*/FirstModel.csdl|res://*/FirstModel.ssdl|res://*/FirstModel.msl|res://*/SecondModel.csdl|res://*/SecondModel.ssdl|res://*/SecondModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> 
    </connectionStrings> 
</configuration> 

此连接字符串包含两种模式元数据 - FirstModel.edmx和SecondModel.edmx。

的另一个问题是强迫EF使用来自这两个文件的映射。每个EDMX文件必须为SSDL和CSDL定义唯一的容器。 ObjectContext提供称为DefaultContainerName的财产。该属性可以直接设置或通过一些构造函数重载。一旦你设置了这个属性,你可以将你的ObjectContext实例绑定到单个EDMX上 - 对于这个场景,你不能设置这个属性。省略DefaultContainerName可能会产生一些后果,因为某些功能和声明可能会停止工作(您将收到运行时错误)。除非您想使用某些高级功能,否则您应该没有POCO问题。如果你使用的是实体对象(重EF实体,你极有可能不得不proplems使用被定义为字符串的实体集的所有方法都依赖于容器由于此我建议使用只在必要时这样的配置 - 交叉车型查询

最后的问题就是产生实体和“强类型”衍生ObjectContext去的方式是修改T4模板,这样一个模板从多个EDMX文件个个读取数据,并生成语境最终实体 - 我已经在我的项目这样做的,它的工作原理默认的T4实现并不遵循前面段落中描述的需要的方法从默认的T4实现派生的ObjectContext取决于单个EDMX和实体容器


这部分是在上次编辑之前编写的。

我离开的信息,其他人只是因为他们中的一些可以在其他情况下,包括与多个数据库的工作是有用的。

ORM等实体框架上对象世界和数据库世界之间的映射的顶部操作。在EF中,对象世界由CSDL描述,数据库世界被描述为SSDL,并且它们之间的映射被描述为MSL(全部仅仅是具有众所周知的模式的XML)。在设计时这些描述是存储在EDMX文件中的模型的一部分。在编译过程中,这些描述是从EDMX中提取的,并且默认作为资源文件包含在已编译的程序集中。

当您创建的实例ObjectContext它接收的连接字符串包含参照CSDL,SSDL和MSL资源文件。 SSDL或MSL不指定include元素来添加来自其他文件的信息。 CSDL提供Using元素,这将允许您重新使用现有映射,但此功能不受设计人员支持。 ConnectionString用于初始化EntityConnection实例,该实例又用于初始化ObjectContext的MetadataWorkspace(运行时映射信息)。 ObjectContext也不提供将多个上下文嵌套到hiearchy中的任何功能。 连接字符串不能包含对这些文件的多个实例的引用。 编辑:它可以。我只是测试它。看到最初的段落。

当你的ObjectContext的实例中运行的LINQ或ESQL查询它usese MSL映射你的实体或POCO类(由CSDL定义)到数据库查询(通过数据库表的SSDL描述定义)。如果它没有这些信息,它将不起作用(并且如果它存储在单独的EDMX中,则不能获得该信息)。

那么如何解决这个问题呢?有几种方法:

  1. 始终考虑:合并你的映射成一个文件(如果有多个文件被用于同一个数据库)。这应该是使用EF的方式,正如您所提到的,您正在查询相同的数据库,因此不需要两个EF模型。
  2. 第二个模型中的重复实体描述。如果您使用EF4和POCO,则可以将来自多个模型的相同描述映射到一个POCO类定义中。我不喜欢这个解决方案,但有时它可以提供帮助。
  3. 定义包含查询(或查询的核心)的数据库视图或存储过程,并将其映射到一个模型中以形成新实体。
  4. 在一个模型中使用DefiningQuery(如果使用从数据库更新功能,您可能需要第三个)并将其映射到新实体。 DefiningQuery是在SSDL中定义的自定义SQL查询,而不是表或视图描述。
  5. 使用Function以及指定数据库查询的自定义CommandText。这与使用DefiningQuery类似,并且具有相同的限制。您必须手动(在EDMX中)将函数的结果映射到新的复杂类型(与映射到新实体的DefiningQuery的另一个区别)。
  6. 定义查询结果的新类型(类型的属性必须与查询中返回的列名称相同)并使用ObjectContext的ExecuteStoreQuery(仅在EF4中)。
  7. 将查询分为两部分,每部分分别在自己的上下文中执行,并使用linq-to-objects获取结果。我不喜欢这个解决方案。

  8. 这一个只是高层次的想法 - 我没有尝试它,我不知道它是否有效。如上所述,运行时间映射取决于从EntityConnection填充的MetadataWorkspace实例的内容。 EntityConnection也提供了直接接收MetadataWorkspace实例的构造函数。所以一般情况下,如果可以从多个EDMX中填充MetadataWorkspace,则不需要多个ObjectContext实例,但是您的映射仍将分为两个EDMX。这将有希望允许您在两个映射文件上编写自定义Linq查询)。 编辑:它应该是可能的,因为如果您在连接字符串中定义多个映射,EF正是如此。

  9. 使用CSDL Using feature将模型分解为多个重用部分。