【问题标题】:Is it possible to create custom methods in entity classes in linq to sql是否可以在 linq to sql 的实体类中创建自定义方法
【发布时间】:2011-03-02 01:31:19
【问题描述】:

我在 SQL 中有一个表 Site,其中包含三个属性 idReviewer1idReviewer2idReviewer3。现在我想在 Site 的实体类上创建一个方法来检查用户是否是审阅者:

partial class Site
{
    public bool IsReviewer(int idUser)
    {
        return idReviewer1 == idUser || idReviewer2 == idUser || idReviewer3 == idUser;
    }
}

我是这样使用它的:

return from s in db.Sites
       where s.IsReviewer(user)
       select s;

但是,Linq to SQL 不知道如何将其转换为 SQL。我收到以下错误消息:

Method 'Boolean IsReviewer(Int32)' has no supported translation to SQL.

我不想写这个:

return from s in db.Sites
       where idReviewer1 == idUser || idReviewer2 == idUser || idReviewer3 == idUser
       select s;

有没有什么方法可以把这个功能放在一个地方,而不需要借助 SQL?

【问题讨论】:

    标签: .net visual-studio-2008 linq-to-sql .net-3.5


    【解决方案1】:

    您可以将该方法实现为存储过程,然后将其作为函数添加到您的 LINQ to SQL 模型中。然后您就可以执行以下操作:

    ISingleResult<Site> sites = db.SelectSitesByReviewer(userId);
    

    或者,您可以将其实现为 用户定义函数 (UDF),这样您就可以在 LINQ 查询中使用它:

    IEnumerable<Site> sites = from site in db.Sites
                              where db.IsReviewer(site.Id, userId)
                              select site;
    

    但是,在定义像您在问题中提到的那样的 LINQ 查询时,我没有发现任何错误。在这种情况下使用存储过程或 UDF 并不会真正为您带来太多好处,并且需要您将一些逻辑从应用程序移到数据库中,这可能符合也可能不符合您的架构。

    相关资源

    【讨论】:

    • UDF 还需要一个 siteid: where db.IsReviewer(site.siteId, userId) 将它放在一个地方的好处是当我想添加另一个审阅者 (idReviewer1..idReviewer4) 时。但这不是一个大问题。我只是在学习...
    【解决方案2】:

    使用 Func 而不是方法调用。

    partial class Site  
    {  
        public static Func<Site, bool> IsReviewer(int idUser)  
        {  
            return (s => s.idReviewer1 == idUser 
              || s.idReviewer2 == idUser 
              || s.idReviewer3 == idUser);  
        }  
    }  
    
    return db.Sites.Where(Site.IsReviewer());
    

    【讨论】:

    • 也是一个不错的(这个确实有效)。但我认为您不能将此解决方案与查询语法一起使用...顺便说一句,最后一条语句需要一个 idUser:return db.Sites.Where(Site.IsReviewer(1));
    • 是的,无法在这个上获得查询语法支持 - 也很好地抓住了 int。
    • 您应该声明 Expression> 以便在 IQueryable 范围内工作。不是吗?
    【解决方案3】:

    我认为您可能基于错误“'Boolean IsReviewer(My.DAL.User)'”将 My.DAL.User 而不是 int 传递到您的方法中。试试 (where s.IsReviewer(user.Id)) 看看是否可行?

    【讨论】:

    • Boolean IsReviewer(My.DAL.User)' 是错误消息。 My.DAL.User 部分是命名空间。
    • 我倾向于同意这个答案。看起来好像您将 User 类型传递给需要 int 的函数,并且编译器错误正在返回无用的错误消息。
    • @Josh:你是对的。我犯了一个复制/粘贴错误。修复了错误信息。
    【解决方案4】:

    不幸的是可能知道,除非您更改(扩展)linq2SQL 查询提供程序。提供者遇到了一个他确实不知道的方法,他不可能知道如何将该方法翻译成 sql。即使对于这种情况,它通常很简单,但它是不可能的(甚至是危险的)。 但你可以用另一种方式来做。 您可以制作一个 delagate(甚至更好的是编译查询),它接受一个站点并执行条件,然后使用方法语法与

    Func<Site,int,Bool> isRevier = (site, idUser) => site.idReviewer1 == idUser || site.idReviewer2 == idUser || site.idReviewer3 == idUser;
    .Where(IsReviewer)
    

    【讨论】:

    • 在使用 Linq(所有方面)时,通常是使用表达式(和委托)的好方法
    • 嗯,现在我得到“方法 'System.Object DynamicInvoke(System.Object[])' 没有支持的 SQL 转换。”。在查询语法中,我使用: where isReviewer(ouc.OrganizationalUnit.Site, idUser)
    • 对不起,我错过了。你应该返回一个表达式是 Expression >( 然后在哪里使用它......当我没有视觉 stuido 时会发生这种情况:) 查询提供程序翻译表达式而不是 funcs funcs 如果你有表达式).. 抱歉
    猜你喜欢
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多