zoukankan      html  css  js  c++  java
  • EntityFramework 7 Join Count LongCount 奇怪问题

    先吐槽一下,EF7 目前来说,真对的起现在的版本命名:"EntityFramework": "7.0.0-beta1"。

    这篇博文纪录一下:当 Linq 查询中使用 Join 语句,然后获取 Count 的时候会报错,而使用 LongCount 却没有任何问题。

    BloggingContext 配置代码:

    using Microsoft.Data.Entity;
    using Microsoft.Data.Entity.Metadata;
    using System.Collections.Generic;
    
    namespace EF7
    {
        public class BloggingContext : DbContext
        {
            public DbSet<Blog> Blogs { get; set; }
            public DbSet<BlogCate> BlogCates { get; set; }
    
            protected override void OnConfiguring(DbContextOptions builder)
            {
                builder.UseSqlServer(@"Server=.;Database=Blogging;Trusted_Connection=True;");
            }
    
            protected override void OnModelCreating(ModelBuilder builder)
            {
                builder.Entity<Blog>()
                    .Key(b => b.BlogId);
                builder.Entity<BlogCate>()
                    .Key(b => b.CateId);
            }
        }
    
        public class Blog
        {
            public int BlogId { get; set; }
            public string Url { get; set; }
            public int BlogCateId { get; set; }
        }
        public class BlogCate
        {
            public int CateId { get; set; }
            public string CateName { get; set; }
        }
    }
    

    BloggingContext 的配置很简单,只有 Blog 和 BlogCate 两个实体,注意我在 OnModelCreating 映射配置的时候,并没有使用 OneToMany 进行外键映射配置,测试代码:

    [Fact]
    public void ConutTestNoJoin()
    {
        using (var context = new BloggingContext())
        {
            var query = from b in context.Blogs
                        select b;
            var countLog = query.LongCount();
            var count = query.Count();
        }
    }
    

    测试结果:

    SQL Server Profiler 捕获 SQL 代码:

    exec sp_executesql N'SELECT COUNT(*)
    FROM [Blog] AS [b]
    WHERE [b].[Url] = @p0',N'@p0 nvarchar(23)',@p0=N'http://www.cnblogs.com/'
    

    注意 Blogs 表中时没有任何数据的,上面测试代码简单的不能再简单了,当然测试结果没什么问题,生成 SQL 代码也是我们想要的格式(COUNT(*)),这种查询时我们一般常用的 Linq 查询方式,也就是查询单个实体集的 Count,还有一种场景是使用 join 关联,然后进行 Where 条件限制,主要是对主表的限制,然后查询主表符合条件的个数,这种场景我们应该使用 Linq 查询时候也会经常遇到,比如下面测试代码:

    [Fact]
    public void ConutTestWithJoin()
    {
        using (var context = new BloggingContext())
        {
            var query = from b in context.Blogs
                        join c in context.BlogCates on b.BlogCateId equals c.CateId
                        where b.Url.Equals("http://www.cnblogs.com/") && c.CateName.Equals("ef7")
                        select b;
            var countLog = query.LongCount();
            var count = query.Count();
        }
    }
    

    上面测试代码中,我对 BlogCates 中的 CateName 进行了“ef7”的条件限制,测试结果:

    详细异常信息:

    Expression of type 'System.Data.Common.DbDataReader' cannot be used for parameter of type 'Microsoft.Data.Entity.Query.QuerySourceScope' of method 'Microsoft.Data.Entity.Query.QuerySourceScope`1[Microsoft.Data.Entity.Metadata.IValueReader] CreateValueReader(Remotion.Linq.Clauses.IQuerySource, Microsoft.Data.Entity.Query.QueryContext, Microsoft.Data.Entity.Query.QuerySourceScope, System.Data.Common.DbDataReader)'

    SQL Server Profiler 捕获 LongCount 生成的 SQL 代码:

    exec sp_executesql N'SELECT [b].[BlogCateId], [b].[BlogId], [b].[Url]
    FROM [Blog] AS [b]
    INNER JOIN [BlogCate] AS [c] ON [b].[BlogCateId] = [c].[CateId]
    WHERE ([b].[Url] = @p0 AND [c].[CateName] = @p1)',N'@p0 nvarchar(23),@p1 nvarchar(3)',@p0=N'http://www.cnblogs.com/',@p1=N'ef7'
    

    LongCount 生成的这段 SQL,你如果仔细观察的话,其实也有问题,我们使用 Linq 明明写的是 LongCount 语句,生成的 SQL 代码应该和我们第一个测试代码生成的一样,也就是 COUNT(*),有可能你认为是 SQL Server Profiler 捕获 SQL 代码问题,你也可以使用 EF7 自己提供的 SQL 代码纪录方式:EntityFramework 7 如何查看执行的 SQL 代码?,测试之后,你会发现:生成的 SQL 和 SQL Server Profiler 是一样的,之前遇到的 short 类型字段生成也是这样,当然我个人觉得可能还有一些其他的 Linq 语句不能被“翻译”,只是现在还未发现而已,捕获生成的 SQL 代码,EF7 确实需要完善下,如果你使用 EF7 觉得这些语句“不安全”的话,你可以只看测试结果就行了,毕竟生成 SQL 只是作为参考,测试结果才是最准确的。

    回到 Count 报错问题上来,这个问题也花了我一些时间,我一开始认为是 join 关联实体 where 条件的问题,然后我把 join 的 where 条件去掉,发现还是会报错,异常提示大概是说参数类型的问题,具体我也不知道是哪边的问题,反正异常提示信息就这么多。而使用 LongCount 是我无意间发现的,因为之前我们获取数量都是使用的 Count 语句,反正我是不知道有个 LongCount,使用 query. 下拉看可以访问到东西的时候,就无意间发现还有个 LongCount,然后没抱希望的试了下,居然可以???然后我就很奇怪,我查询出来的结果集数量总共不到几百,远远还没达到 Long 的级别,然后新建测试项目,最后发现还是会出现这个问题,这边只能纪录一下这个“奇怪”的问题。

    对于我来说,好消息是:开发项目中可以使用 LongCount,来避免 Count 报错问题,但总感觉心里不踏实,这种 join where 条件限制来获取 Count 的方式,我们应该会经常用到,如果你看出是哪方面问题了,还请指教,感谢!


    已提交至 EntityFramework 7 issues:Use EF7, Linq Join Count is error

  • 相关阅读:
    linux mint 17编译android 2.3.1错误记录
    android字母索引实现ListView定位
    android实现emoji输入
    shell管道与重定向
    c3p0配置记录
    ubuntu13 eclipse菜单栏失效解决
    Proxy实现java动态代理
    ubuntu13启动屏幕亮度0解决方法
    cookie和session笔记
    linux mysql中文乱码解决
  • 原文地址:https://www.cnblogs.com/xishuai/p/ef7-linq-join-count-longcount-error.html
Copyright © 2011-2022 走看看