web-dev-qa-db-ja.com

テーブル値関数とエンティティフレームワーク

Entity Frameworkを使用して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経由でfuncを呼んでいる方法です

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

そして、私はこのエラーを受け取ります:


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

私が欠けているものについて何かアイデアはありますか?私はグーグルで見つけたほとんどすべてのヒントを試しましたが、どれも私の問題を解決しませんでした。

ここに含まれていないコードを確認する必要がある場合は、質問してください。追加します。

13
BrunoPugliese

これは、テーブル値UDFを直接サポートするEntityFrameworkの新機能に関する非常に優れた記事です。 Entity Frameworkでのテーブル値関数のサポートに関するMSDNブログ

詳細については、この記事で詳細を説明します。 EDMおよびストア関数はLINQで公開されています。

テーブル値UDFの最近のサポートの大きな利点の1つは、全文検索機能のサポートです。詳細については、こちらをご覧ください: データベースオブジェクトを含む全文検索機能

5
devinbost

[テスト済み]使用:

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
13
Nina

これは、テーブルパラメータを関数に送信し、テーブル値関数の値を返す方法です。

C#:

var fooDataTable = new DataTable();
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
0
StepUp