C# 表值函数和实体框架
我试图用实体框架执行一个TVF,但由于某些原因,它就是不起作用。 也许外面的任何人都能帮我解决这个问题 以下是代码示例: 这就是功能:C# 表值函数和实体框架,c#,linq,entity-framework,ef-code-first,user-defined-functions,C#,Linq,Entity Framework,Ef Code First,User Defined Functions,我试图用实体框架执行一个TVF,但由于某些原因,它就是不起作用。 也许外面的任何人都能帮我解决这个问题 以下是代码示例: 这就是功能: CREATE FUNCTION [dbo].[udf_profileSearch] (@keywords NVARCHAR(3000)) RETURNS @results TABLE ( [Id] [int] NULL, [SubCategoryId] [int] NULL, [UserId] [int] NULL, [Smal
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
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
)
我的DbContext文件(名为EAjudaContext)中有这个
我得到了这个错误:
'eAjudaConnection.udf_profileSearch' cannot be resolved into a valid type or function.
“eAjudaConnection.udf_profileSearch”无法解析为有效的类型或函数。
你知道我遗漏了什么吗?
我几乎尝试了在谷歌上找到的每一个技巧,但没有一个能解决我的问题
如果您需要查看此处未包含的任何代码,请询问,我将添加它。这是一篇非常好的文章,介绍了Entity Framework的更新功能,这些功能直接支持表值UDF
为了更深入,本文提供了重要的细节
最近支持表值UDF的最大优点之一是支持全文搜索功能。请在此处阅读更多信息:[已测试]
使用:
为输出结果声明一个类:
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);
}
现在你可以打电话/加入
表值函数如下所示:
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
这是一种向函数发送表参数并返回表值函数值的方法
C#:
SQL表值函数:
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
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
当我直接调用表值函数时,这确实有效,但是如果我加入它(使用let
关键字)并从另一个表向它传递一个值,则会出现“无法转换为存储表达式”错误。还有什么方法可以这样做吗?api改变了。OnModelCreating中的代码应该是:modelBuilder.Conventions.Add(新函数convention(“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
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();
public class CarFieldsDTO
{
public int ID { get; set; }
public string CarNumber { get; set; }
public DateTime? ArriveDate { get; set; }
public IEnumerable<CarFieldsDTO> Fields { get; set; }
}
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