linq 加入 guid 和字符串列

Posted

技术标签:

【中文标题】linq 加入 guid 和字符串列【英文标题】:linq join on guid and string column 【发布时间】:2012-08-26 13:49:39 【问题描述】:

我是 linq 的新手。我需要运行一个连接两列的查询(AnonymousUser.AnonymousIduniqueidentifier 和 comment.UserId 是 nvarchar(100)),如下所示:

        using (CommentEntities db = new CommentEntities())
        
            // filteredComments is a query that is not run until the next .ToList()
            IQueryable<Comment> filteredComments = this.CommentGetList(...);
            var query = from comment in filteredComments
                         // following line is the syntax error, because columns' types don't match
                         join user in db.AnonymousUsers on comment.UserId equals user.AnonymousId into gj
                         from userNull in gj.DefaultIfEmpty()
                         select new CommentWithName
                         
                             Comment = comment,
                             UserId = comment.UserId,
                             FirstName = (userNull == null ? "" : userNull.Name),
                             LastName = "",
                             Email = (userNull == null ? "" : userNull.Email)
                         ;
            return query.ToList();
        

首先我很高兴使用.ToString() 编写查询!事实证明,实体框架不知道如何将其转换为 sql。 Guid.Parse(string) 也是如此。此外,new Guid(string) 不能在 linq 中用于实体(仅允许无参数构造函数)!

所以在搜索之后,我发现在 EF 4.0 中不可能做这样的事情!我将我的代码迁移到了一个我不太满意的存储过程。

是否可以告诉实体框架在 SQL 中使用CAST

这个问题有什么解决办法吗?有什么方法可以将逻辑带入代码中?

注意:我的意思是一次完成。否则,一种可能的解决方案是从第一个表中获取实体,并将 Id 放入列表中并从第二个表中获取实体。

【问题讨论】:

如果 comment.UserId 是 GUID 的字符串表示形式,那么将该列也转换为唯一标识符会更容易吗?这可能是比让实体框架尝试在 SQL 中为您执行此转换更好的解决方案。 不幸的是,它并不总是 GUID。根据用户类型,它可能是Guidint 你试过用Guid.Parse(string)代替new Guid(string)吗? 你试过了吗 :D ??不成功:LINQ to Entities 无法识别方法 'System.Guid Parse(System.String)' 方法,并且该方法无法转换为存储表达式。 【参考方案1】:

在应用这些方法之前调用 toList()。喜欢:

var Product = db.Products.Where(p => p.ProductId == Guid.Parse("B4E913F9-166C-49BA-AADE-6DB889D1756F")).Single();

会扔一个

c# LINQ to Entities 无法识别方法“System.Guid Parse”(System.String)' 方法,并且该方法无法翻译成存储表达式

但这有效:

var Product = db.Products.ToList().Where(p => p.ProductId == Guid.Parse("B4E913F9-166C-49BA-AADE-6DB889D1756F")).Single()

p.s.:我认为您将失去延迟加载,但您可以在调用 .ToList() 之前使用 .Include 进行急切加载。

【讨论】:

如果它适用于两个没有关系的表,那么使用急切加载将是一个好主意。 P.S:表 Comment 和 AnonymousUser 之间没有关系 您最终将使用此选项将整个列表拉入内存。仅当产品表很小时才这样做。【参考方案2】:

如果您的list 是对象列表,您可以将其转换为以 Guid 作为标识符的类型,首先创建新的匿名类型,然后根据UserId 过滤它,当然UserIdint 类型, 不会包含在 join 中:

     int output = 0;

     var secondList = list.Where(x=>!int.TryParse(x.UserID, out output))
                     .Select(x=>new Comment = x, ID = new Guid(x.UserID))
                     .ToList();

现在您可以使用 secondList 在 db 上运行查询。

【讨论】:

我没有提到list 的类型是IQueryable&lt;Comment&gt; 所以你的意思是它是一个数据库项目,在这种情况下我会提供使用存储过程。 +1。那么你同意EF没有办法做到这一点?那么新版本的 EF 呢? @Ashkan,似乎 EF 4.0 是不可能的(有 99% 的机会),但 EF 4.1 可能是可能的,而且我不擅长 4.1,无论如何,这里的主要问题是糟糕的设计,如果是我的,首先我会修复糟糕的设计问题,然后我会考虑如何使用 EF,... @JoaoLeme,我的意思是如果不加载到内存中就不可能做到这一点,如果你看到 OPs 其他 cmets,似乎 comment 表太大,实际上不可能在内存中获取它.

以上是关于linq 加入 guid 和字符串列的主要内容,如果未能解决你的问题,请参考以下文章

通过字符串列的最大值和最小值查找数据行中的值是不是相等

计算字符串列之间的相关性

如何查找和替换字符串列中数字之间的空格?

用LINQ将select中两列的结果合并到一个数组中?

如何在poedit中编辑原始字符串列?

根据变长分隔符拆分熊猫字符串列