在 LINQ 的 Select 语句中执行一些操作

本文关键字:执行 操作 语句 LINQ Select | 更新日期: 2023-09-27 18:34:57

我有一个控制器操作方法,它返回 IQueryable< AnswerDTO>其中有一个名为"Sequence"的字段。我想在经过一些计算后设置此字段。我的方法是

var answer = from dfi in _db.DiaryFormInstances
 //Some Query with LINQ
 select new AnswerDTO()
 {
     Value = dfit.Value,
     //How to perform this operation?
     Sequence = Convert.ToInt32(fti.ItemName.Substring(fti.ItemName.LastIndexOf("_")+1)),
     LastModifiedDate = dfit.LastModifiedDate.Value,
     LastModifiedByID = dfit.LastModifiedByID.Value
 };

如何在选择语句中像这样设置序列属性?

Sequence = Convert.ToInt32(fti.ItemName.Substring(fti.ItemName.LastIndexOf("_")+1))

如果我在我的操作方法中执行查询,那么我可以轻松执行此操作。但是我想返回 IQueryable,并且我不想在我的操作方法中执行查询。

我希望 web api 将执行查询,执行后它将正确设置序列属性。

在 LINQ 的 Select 语句中执行一些操作

在调查了 Linq to Entities 中可用的函数后,似乎无法以您希望的方式提取数字。

最好的办法是在数据库中创建一个可以调用的自定义函数。为此,请先在数据库中创建以下函数(例如,可以直接使用 SSMS 创建它(:

CREATE FUNCTION ExtractSequence
(
    @sequenceString NVARCHAR(50)
)
RETURNS INT
AS
BEGIN
    RETURN CAST(RIGHT(@sequenceString, CHARINDEX('_', REVERSE('_' + @sequenceString)) - 1) AS INT)
END
GO

接下来,您需要包含 https://codefirstfunctions.codeplex.com/包,它在NuGet上,只需搜索CodeFirstStoreFunctions即可。

添加上述包后,您需要将modelBuilder.Conventions.Add(new FunctionsConvention("dbo", this.GetType()));添加到上下文类的OnModelCreating方法中,例如

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add(new FunctionsConvention("dbo", this.GetType()));
}

接下来,您还需要将以下内容添加到上下文类中:

// First parameter should always be CodeFirstDatabaseSchema, this is just a convention used by the store functions package
// The second parameter should match the name of the function in the DB. You can call the method something else but I'd keep it the same as the function name too
[DbFunction("CodeFirstDatabaseSchema", "ExtractSequence")]
public static int ExtractSequence(string sequenceString)
{
    // No need to provide an implementation as this is like a placeholder for the DB function you created in the DB in the first step
    throw new NotSupportedException();
}

最后,可以在 Linq to Entity 表达式中使用新函数,因此可以将选择更改为如下所示:

var answer = from dfi in _db.DiaryFormInstances
select new AnswerDTO()
{
    Value = dfit.Value,
    Sequence = MyDbContext.ExtractSequence(fti.ItemName), // Change MyDbContext to whatever your context class is
    LastModifiedDate = dfit.LastModifiedDate.Value,
    LastModifiedByID = dfit.LastModifiedByID.Value
};