Как я могу выполнить функцию Oracle из выражения LINQ в Entity Framework 4? - PullRequest
1 голос
/ 14 октября 2010

Я использую Visual Studio 2010, C #, Entity Framework 4 и Oracle 10g.

Мне нужно иметь возможность возвращать результат функции базы данных как скалярное свойство анонимного типа.

В моей схеме Oracle есть две таблицы: PARENT и CHILD и функция FNC_ADD. Я создал модель объекта, используя шаблон модели данных объекта ADO.NET для Visual Studio, включая таблицы и функцию.

Раздел StorageModels моего файла .edmx выглядит так:

<!-- 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>

Я создал метод расширения, чтобы определить функцию для модели данных сущности, которая выглядит следующим образом:

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();
    }
}

Я вызываю функцию в выражении 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);
        }
    }
}

Все компилируется правильно, но когда я запускаю код, я получаю это:

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.

Что я делаю не так?

Ответы [ 2 ]

3 голосов
/ 14 октября 2010

Используйте пространство имен 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();
    }
}

Если вы правильно указали пространство имен, все работает гладко.

3 голосов
/ 14 октября 2010

Ваше пространство имен с EdmFunctionAttribute выглядит подозрительно.Это похоже на тип CLR, а не на склад. Это сообщение в блоге может помочь вам разобраться в этом.

...