【问题标题】:Table Valued Function and Entity Framework表值函数和实体框架
【发布时间】:2013-08-29 13:25:56
【问题描述】:

我正在尝试使用实体框架执行 TVF,但由于某种原因它不起作用。 也许那里的任何人都可以帮助我解决问题。

以下是代码示例:

这就是函数:

CREATE FUNCTION [dbo].[udf_profileSearch]
(@keywords NVARCHAR(3000))
RETURNS @results TABLE 
(
    [Id] [int] NULL,
    [SubCategoryId] [int] NULL,
    [UserId] [int] NULL,
    [SmallDescription] [nvarchar](250) NULL,
    [DetailedDescription] [nvarchar](500) NULL,
    [Graduation] [nvarchar](140) NULL,
    [Experience] [nvarchar](500) NULL,
    [IsChat] [bit] NULL,
    [IsEmail] [bit] NULL,
    [MinuteCost] [decimal](18, 2) NOT NULL,
    [TestimonyRate] [int] NULL,
    [TestimonyQuantity] [int] NULL,
    [StatusId] [int] NULL
)

AS
BEGIN
IF(@keywords != '')
    BEGIN
        insert @results
            SELECT p.Id, p.SubCategoryId, p.UserId, p.SmallDescription, p.DetailedDescription, p.Graduation, 
                        p.Experience, p.IsChat, p.IsEmail, p.MinuteCost, p.TestimonyRate, p.TestimonyQuantity, 
                        p.StatusId FROM 
            Profile p inner join ProfileSearchKeyword psk
            ON p.Id = psk.ProfileId
            WHERE CONTAINS(psk.*,@keywords)
    END
ELSE 
    BEGIN
        insert @results
            SELECT p.* FROM 
            Profile p inner join ProfileSearchKeyword psk
            ON p.Id = psk.ProfileId
    END
RETURN
END

我的 DbContext 文件中有这个(名为 EAjudaContext)

[EdmFunction("eAjudaConnection", "udf_profileSearch")]
    public virtual IQueryable<Profile> udf_profileSearch(string keywords)
    {
        var keywordsParameter = keywords != null ?
            new ObjectParameter("keywords", keywords) :
            new ObjectParameter("keywords", typeof(string));

        return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<Profile>("eAjudaConnection.udf_profileSearch(@keywords)", keywordsParameter);
    }

这就是我通过 LINQ 调用函数的方式

var result = from ps in eAjudaCtx.udf_profileSearch("query") select ps

我得到这个错误:


'eAjudaConnection.udf_profileSearch' cannot be resolved into a valid type or function.

关于我缺少什么的任何想法? 我已经尝试了几乎所有在谷歌上找到的技巧,但没有一个能解决我的问题。

如果您需要查看此处未包含的任何代码,请询问,我会添加。

【问题讨论】:

    标签: c# linq entity-framework ef-code-first user-defined-functions


    【解决方案1】:

    这是一篇非常好的文章,介绍了实体框架的新特性,这些特性为表值 UDF 提供了直接支持。 MSDN blog on Table-Valued Function Support in Entity Framework.

    为了更深入,本文提供了重要的细节。 EDM and store functions exposed in LINQ.

    最近支持表值 UDF 的一大优势在于支持全文搜索功能。在此处阅读更多信息:Full text search features involving database objects.

    【讨论】:

      【解决方案2】:

      [已测试] 使用:

      Install-Package EntityFramework.CodeFirstStoreFunctions
      

      为输出结果声明一个类:

      public class MyCustomObject
      {
         [Key]
         public int Id { get; set; }
         public int Rank { get; set; }
      }
      

      在你的 DbContext 类中创建一个方法

      [DbFunction("MyContextType", "SearchSomething")]
      public virtual IQueryable<MyCustomObject> SearchSomething(string keywords)
      {
         var keywordsParam = new ObjectParameter("keywords", typeof(string)) 
                                 { 
                                    Value = keywords 
                                  };
          return (this as IObjectContextAdapter).ObjectContext
          .CreateQuery<MyCustomObject>(
           "MyContextType.SearchSomething(@keywords)", keywordsParam);
      }
      

      添加

      public DbSet<MyCustomObject> SearchResults { get; set; }
      

      到你的 DbContext 类

      添加覆盖的OnModelCreating方法:

      modelBuilder.Conventions
      .Add(new CodeFirstStoreFunctions.FunctionsConvention<MyContextType>("dbo"));
      

      现在你可以打电话/加入 像这样的表值函数:

      CREATE FUNCTION SearchSomething
      (   
          @keywords nvarchar(4000)
      )
      RETURNS TABLE 
      AS
      RETURN 
      (SELECT KEY_TBL.RANK AS Rank, Id
      FROM MyTable 
      LEFT JOIN freetexttable(MyTable , ([MyColumn1],[MyColumn2]), @keywords) AS KEY_TBL      
      ON MyTable.Id = KEY_TBL.[KEY]  
      WHERE KEY_TBL.RANK > 0   
      )
      GO
      

      【讨论】:

      • 当我直接调用我的表值函数时,这确实有效,但如果我加入它(使用let 关键字)并从另一个表传递一个值给它,它会给我“无法转换为商店表达式”错误。有没有办法做到这一点?
      • API 已更改。 OnModelCreating 中的代码应如下所示:modelBuilder.Conventions.Add(new FunctionsConvention("dbo"));
      【解决方案3】:

      这是一种向函数发送表参数并返回表值函数值的方法。

      C#:

      var fooDataTable = new DataTable();
      var ids = new List<FooDto>();
      if (ids.Count > 0)
      {
          fooDataTable.Columns.Add("ID", typeof(int));
          fooDataTable.Columns.Add("CarNumber");
          fooDataTable.Columns.Add("ArriveDate", typeof(DateTime));                
      
          foreach (var car in ids)
          {
              fooDataTable.Rows.Add(car?.ID, car?.CarNumber, car?.ArriveDate);
          }
      }
      
      SqlParameter cdIDs = new SqlParameter("@ListToCalc", SqlDbType.Structured);
      cdIDs.Value = fooDataTable;
      cdIDs.TypeName = "tp_CarList";
      
      var template = new CarFieldsDTO
      {
          Fields = db.Database.SqlQuery<fn_Car_Result>
              ("SELECT * FROM dbo.fn_Car(@ListToCalc)", cdIDs)
                  .Select(field => new CarFieldsDTO
                  {
                      ID = field.ID,
                      CarNumber = field.CarNumber,
                      ArriveDate = field.ArriveDate,                    
                  }).ToList()
      };
      
      var fields = new List<CarFieldsDTO> { template };
      return fields.AsQueryable();
      

      dbDbContext

      DTO:

      public class CarFieldsDTO
      {        
          public int ID { get; set; }
      
          public string CarNumber { get; set; }
      
          public DateTime? ArriveDate { get; set; }
      
          public IEnumerable<CarFieldsDTO> Fields { get; set; }
      }
      

      SQL 表值函数:

      ALTER  FUNCTION [dbo].[fn_Car]
      (
            @ListToCalc tp_CarList READONLY
      )
      RETURNS TABLE
      AS
          RETURN
          (
              SELECT l.ID
                     , l.CarNumber
                     , l.ArriveDate
              FROM @ListToCalc l
              INNER JOIN Stations as sf ON sf.ID = l.id_StationFrom
          )
      

      用户定义的表格类型:

      CREATE TYPE [dbo].[tp_CarList] AS TABLE(
          [ID] [int] NOT NULL,
          [CarNumber] [varchar](12) NULL,
          [ArriveDate] [datetime] NULL    
      )
      GO
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-06
        • 1970-01-01
        • 2013-10-14
        相关资源
        最近更新 更多