简体   繁体   English

如何在Entity Framework 4中的LINQ表达式中执行Oracle函数?

[英]How can I execute an Oracle function from within a LINQ expression in Entity Framework 4?

I am using Visual Studio 2010, C#, Entity Framework 4 and Oracle 10g. 我正在使用Visual Studio 2010,C#,实体框架4和Oracle 10g。

I need to be able to return the result of a database function as a scalar property of an anonymous type. 我需要能够将数据库函数的结果作为匿名类型的标量属性返回。

My Oracle schema has two tables, PARENT and CHILD, and a function FNC_ADD. 我的Oracle模式有两个表PARENT和CHILD,以及一个函数FNC_ADD。 I have created an entity model using the Visual Studio ADO.NET Entity Data Model template, including both tables and the function. 我已经使用Visual Studio ADO.NET实体数据模型模板创建了一个实体模型,包括表和函数。

The StorageModels section of my .edmx file looks like this: 我的.edmx文件的StorageModels部分如下所示:

<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="LINQtest2Model.Store" Alias="Self" Provider="Devart.Data.Oracle" ProviderManifestToken="ORA" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
    <EntityContainer Name="LINQtest2ModelStoreContainer">
      <EntitySet Name="CHILD" EntityType="LINQtest2Model.Store.CHILD" store:Type="Tables" Schema="LINQ_TEST" />
      <EntitySet Name="PARENT" EntityType="LINQtest2Model.Store.PARENT" store:Type="Tables" Schema="LINQ_TEST" />
      <AssociationSet Name="LINQ_TEST_FK_PARENT" Association="LINQtest2Model.Store.LINQ_TEST_FK_PARENT">
        <End Role="PARENT" EntitySet="PARENT" />
        <End Role="CHILD" EntitySet="CHILD" />
      </AssociationSet>
    </EntityContainer>
    <EntityType Name="CHILD">
      <Key>
        <PropertyRef Name="CHILD_ID" />
      </Key>
      <Property Name="CHILD_ID" Type="decimal" Nullable="false" />
      <Property Name="PARENT_ID" Type="decimal" Nullable="false" />
      <Property Name="F_NAME" Type="VARCHAR2" MaxLength="20" />
      <Property Name="L_NAME" Type="VARCHAR2" MaxLength="50" />
      <Property Name="CREATE_DATE" Type="DATE" Nullable="false" />
    </EntityType>
    <EntityType Name="PARENT">
      <Key>
        <PropertyRef Name="PARENT_ID" />
      </Key>
      <Property Name="PARENT_ID" Type="decimal" Nullable="false" />
      <Property Name="F_NAME" Type="VARCHAR2" MaxLength="20" />
      <Property Name="L_NAME" Type="VARCHAR2" MaxLength="50" />
      <Property Name="CREATE_DATE" Type="DATE" Nullable="false" />
    </EntityType>
    <Association Name="LINQ_TEST_FK_PARENT">
      <End Role="PARENT" Type="LINQtest2Model.Store.PARENT" Multiplicity="1">
        <OnDelete Action="Cascade" />
      </End>
      <End Role="CHILD" Type="LINQtest2Model.Store.CHILD" Multiplicity="*" />
      <ReferentialConstraint>
        <Principal Role="PARENT">
          <PropertyRef Name="PARENT_ID" />
        </Principal>
        <Dependent Role="CHILD">
          <PropertyRef Name="PARENT_ID" />
        </Dependent>
      </ReferentialConstraint>
    </Association>
    <Function Name="FNC_ADD" ReturnType="decimal" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="LINQ_TEST">
      <Parameter Name="V1" Type="decimal" Mode="In" />
      <Parameter Name="V2" Type="decimal" Mode="In" />
    </Function>
  </Schema></edmx:StorageModels>

I created an extension method to define the function for the entity data model that looks like this: 我创建了一个扩展方法来定义实体数据模型的功能,如下所示:

public partial class LINQtest2Entities
{
    [EdmFunction("LINQtest2Model", "FNC_ADD")]
    public decimal FNC_ADD(decimal V1, decimal V2)
    {
        // don’t need to implement the function
        throw new ApplicationException();
    }
}

I call the function in a LINQ expression like this: 我在LINQ表达式中调用该函数,如下所示:

using (var context = new LINQtest2Entities())
{
    var parents = from p in context.PARENTs
                  select new
                  {
                      children = from c in p.Children
                                 select new
                                 {
                                     p.PARENT_ID,
                                     c.CHILD_ID,
                                     a = context.FNC_ADD(p.PARENT_ID, c.CHILD_ID)
                                 }
                  };

    foreach (var parent in parents)
    {
        foreach (var child in parent.children)
        {
            Console.WriteLine("P {0}  C {1}  A {2}", child.PARENT_ID, child.CHILD_ID, child.a);
        }
    }
}

Everything compiles correctly, but when I run the code I get this: 一切都能正确编译,但是当我运行代码时,我得到了:

The specified method 'System.Decimal FNC_ADD(System.Decimal, System.Decimal)' on the type 'LINQtest2.LINQtest2Entities' cannot be translated into a LINQ to Entities store expression.

What am I doing wrong? 我究竟做错了什么?

Your namespace arg to EdmFunctionAttribute looks suspicious. 您到EdmFunctionAttribute名称空间arg看起来可疑。 That looks like a CLR type, not a store space. 看起来像CLR类型,而不是存储空间。 This blog post might help you sort that out. 这篇博客文章可以帮助您解决问题。

Use the Model.Store namespace: 使用Model.Store命名空间:

public partial class LINQtest2Entities
{
    [EdmFunction("LINQtest2Model.Store", "FNC_ADD")]
    public decimal FNC_ADD(decimal V1, decimal V2)
    {
        // don’t need to implement the function
        throw new ApplicationException();
    }
}

In case you have provided the namespace correctly everything works smoothly. 如果您正确提供了名称空间,那么一切都会顺利进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM