<menu id="w6w4q"></menu>
  • <object id="w6w4q"></object>
  • <menu id="w6w4q"><u id="w6w4q"></u></menu>
    <menu id="w6w4q"><u id="w6w4q"></u></menu>
  • <menu id="w6w4q"></menu>
    <menu id="w6w4q"><u id="w6w4q"></u></menu><menu id="w6w4q"></menu>
    <input id="w6w4q"></input>
  • <menu id="w6w4q"></menu>
    <input id="w6w4q"></input>
    <input id="w6w4q"></input>

    EFCore执行Sql语句的方法:FromSql与ExecuteSqlCommand

    前言

    在EFCore中执行Sql语句的方法为:FromSql与ExecuteSqlCommand;在EF6中的为SqlQuery与ExecuteSqlCommand,而FromSql和SqlQuery有很大区别,FromSql返回值为IQueryable,因此为延迟加载的,可以与Linq扩展方法配合使用,但是有不少的坑(EFCore版本为1.1.0),直接执行Sql语句的建议不要使用FromSql,但是EFCore中并没有提供SqlQuery方法,因此下面会贴出SqlQuery的实现代码供大家参考,以便在EFCore中能使用。

    FromSql和ExecuteSqlCommand的使用

    测试时使用了SqlServer2008和SqlServer Profiler进行Sql语句捕捉,EFCore的版本为1.1.0。

    测试的Entity Model与DbContext

    public class MSSqlDBContext : DbContext
        {
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder.UseSqlServer(@"data source=localhost;initial catalog=TestDB;Integrated Security=True;");
            }
            public DbSet<Person> Person { get; set; }
            public DbSet<Address> Address { get; set; }
    }
    
        [Table(nameof(Person))]
        public class Person
        {
            public int id { get; set; }
            public string name { get; set; }
            [Column(TypeName = "datetime")]
            public DateTime? birthday { get; set; }
            public int? addrid { get; set; }
    }
    
        [Table(nameof(Address))]
        public class Address
        {
            public int id { get; set; }
            public string fullAddress { get; set; }
            public double? lat { get; set; }
            public double? lon { get; set; }
        }
    

      

    ExecuteSqlCommand

    EFCore的ExecuteSqlCommand和EF6的一样,执行非查询的Sql语句:

    var db = new MSSqlDBContext();
    2             db.Database.ExecuteSqlCommand($"update {nameof(Person)} set [email protected] where [email protected]", new[] 
    3             {
    4                 new SqlParameter("name", "tom1"),
    5                 new SqlParameter("id", 1),
    6             });
    

      

    FromSql

    官方参考文档:https://docs.microsoft.com/en-us/ef/core/querying/raw-sql

    简单使用

     var db = new MSSqlDBContext();
    2             var name = "tom";
    3             var list = db.Set<Person>().FromSql($"select * from {nameof(Person)} where {nameof(name)}[email protected]{nameof(name)} ", 
    4                 new SqlParameter(nameof(name), name)).ToList();
    

      生成的Sql:

    exec sp_executesql N‘select * from Person where [email protected] 
    ‘,N‘@name nvarchar(3)‘,@name=N‘tom‘
    

      

    注意:

    默认生成的为Person的Model,如果Select获取的字段中不包含Person中的某字段就会抛异常了,例如:下面的语句只获取name字段,并没有包含Person的其他字段,那么抛异常:The required column ‘id‘ was not present in the results of a ‘FromSql‘ operation.

     

    db.Set<Person>().FromSql($"select name from {nameof(Person)} ").ToList();
    

      那么改为:

    db.Set<Person>().Select(l => l.name).FromSql($"select name from {nameof(Person)} ").ToList();
    

      

    执行存储过程

     var db = new MSSqlDBContext();
    db.Set<Person>().FromSql("exec testproc @id", new SqlParameter("id", 1)).ToList();
    

      生成的Sql:

    exec sp_executesql N‘exec testproc @id
    ‘,N‘@id int‘,@id=1
    

      

    与Linq扩展方法配合使用

    var db = new MSSqlDBContext();
    db.Set<Person>().FromSql($"select * from {nameof(Person)} where [email protected] ", new SqlParameter("@name", "tom"))
                    .Select(l => new { l.name, l.birthday }).ToList();
    

      生成的Sql:

    exec sp_executesql N‘SELECT [l].[name], [l].[birthday]
    FROM (
        select * from Person where [email protected] 
    ) AS [l]‘,N‘@name nvarchar(3)‘,@name=N‘tom‘
    

      

    inner join + order by

    var db = new MSSqlDBContext();
                  (from p in db.Set<Person>().FromSql($"select * from {nameof(Person)} ")
                  join a in db.Set<Address>().Where(l => true)
                  on p.addrid equals a.id
                  select new { p.id, p.name, a.fullAddress }).OrderBy(l => l.id).ToList();
    

      生成的Sql:

    SELECT [p].[id], [p].[name], [t].[fullAddress]
    FROM (
        select * from Person 
    ) AS [p]
    INNER JOIN (
        SELECT [l0].*
        FROM [Address] AS [l0]
    ) AS [t] ON [p].[addrid] = [t].[id]
    ORDER BY [p].[id]
    

      

    left join + order by

    var db = new MSSqlDBContext();
                  (from p in db.Set<Person>().FromSql($"select * from {nameof(Person)} ")
                  join a in db.Set<Address>().Where(l => true)
                 on p.addrid equals a.id into alist
                  from a in alist.DefaultIfEmpty()
                  select new { p.id, p.name, fullAddress = a == null ? null : a.fullAddress }).OrderBy(l => l.id).ToList();
    

      生成的Sql:(生成的Sql很有问题,order by后面多了[p].[addrid],而且生成的select的字段也是多了)

    SELECT [p].[id], [p].[addrid], [p].[birthday], [p].[name], [t].[id], [t].[fullAddress], [t].[lat], [t].[lon]
    FROM (
        select * from Person 
    ) AS [p]
    LEFT JOIN (
        SELECT [l0].[id], [l0].[fullAddress], [l0].[lat], [l0].[lon]
        FROM [Address] AS [l0]
    ) AS [t] ON [p].[addrid] = [t].[id]
    ORDER BY [p].[id], [p].[addrid]
    

      将FromSql换成Where扩展方法试试:

                 (from p in db.Set<Person>().Where(l => true)
                  join a in db.Set<Address>().Where(l => true)
                  on p.addrid equals a.id into alist
                  from a in alist.DefaultIfEmpty()
                  select new { p.id, p.name, fullAddress = a == null ? null : a.fullAddress }).OrderBy(l => l.id).ToList();
    

      EFCore生成的Sql(order by后面还是多了[addrid],select的字段也是多了):

    SELECT [l].[id], [l].[addrid], [l].[birthday], [l].[name], [t].[id], [t].[fullAddress], [t].[lat], [t].[lon]
    FROM [Person] AS [l]
    LEFT JOIN (
        SELECT [l1].[id], [l1].[fullAddress], [l1].[lat], [l1].[lon]
        FROM [Address] AS [l1]
    ) AS [t] ON [l].[addrid] = [t].[id]
    ORDER BY [l].[id], [l].[addrid]
    

      而在EF6中生成的Sql,比EFCore的生成好多了:

    SELECT 
        [Project1].[id] AS [id], 
        [Project1].[name] AS [name], 
        [Project1].[C1] AS [C1]
        FROM ( SELECT 
            [Extent1].[id] AS [id], 
            [Extent1].[name] AS [name], 
            CASE WHEN ([Extent2].[id] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE [Extent2].[fullAddress] END AS [C1]
            FROM  [dbo].[Person] AS [Extent1]
            LEFT OUTER JOIN [dbo].[Address] AS [Extent2] ON [Extent1].[addrid] = [Extent2].[id]
        )  AS [Project1]
        ORDER BY [Project1].[id] ASC
    

      

    结果说明

    FromSql不能代替原来EF6的SqlQuery使用,而且结合Linq扩展方法使用的时候生成的Sql会存在一些问题(EFCore版本为:1.1.0),那么为了能在EFCore中执行Sql查询语句,下面提供对SqlQuery方法的实现。

    SqlQuery的实现

    public static IList<T> SqlQuery<T>(DbContext db, string sql, params object[] parameters)
                where T : new()
            {
                //注意:不要对GetDbConnection获取到的conn进行using或者调用Dispose,否则DbContext后续不能再进行使用了,会抛异常
                var conn = db.Database.GetDbConnection();
                try
                {
                    conn.Open();
                    using (var command = conn.CreateCommand())
                    {
                        command.CommandText = sql;
                        command.Parameters.AddRange(parameters);
                        var propts = typeof(T).GetProperties();
                        var rtnList = new List<T>();
                        T model;
                        object val;
                        using (var reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                model = new T();
                                foreach (var l in propts)
                                {
                                    val = reader[l.Name];
                                    if (val == DBNull.Value)
                                    {
                                        l.SetValue(model, null);
                                    }
                                    else
                                    {
                                        l.SetValue(model, val);
                                    }
                                }
                                rtnList.Add(model);
                            }
                        }
                        return rtnList;
                    }
                }
                finally
                {
                    conn.Close();
                }
            }
    

      使用:

    var db = new MSSqlDBContext();
                string name = "tom";
                var list = SqlQuery<PAModel>(db,
                    $" select p.id, p.name, a.fullAddress, a.lat, a.lon " +
                    $" from ( select * from {nameof(Person)} where {nameof(name)}[email protected]{nameof(name)} ) as p " +
                    $" left join {nameof(Address)} as a on p.addrid = a.id ",
                    new[] { new SqlParameter(nameof(name), name) });
    

      生成的Sql:

    exec sp_executesql N‘ select p.id, p.name, a.fullAddress, a.lat, a.lon  from ( select * from Person where [email protected] ) as p  left join Address as a on p.addrid = a.id ‘,N‘@name nvarchar(3)‘,@name=N‘tom‘
    
    相关文章
    相关标签/搜索
    三期内必开一期特四肖白小姐资料 一肖中特2020年香港马会最快报码开奖结果直播历史记录免费资料网 荆州市| 凤山县| 浦北县| 景宁| 章丘市| 宁海县| 桂林市| 承德县| 仪陇县| 开阳县| 昆山市| 当阳市| 汝南县| 道孚县| 石首市| 运城市| 沾益县| 辰溪县| 马鞍山市| 东源县| 广河县| 都昌县| 丰顺县| 武安市| 祁连县| 玉树县| 都江堰市| 二连浩特市| 武义县| 昭觉县| 河间市| 德化县| 江油市| 萨嘎县| 芷江| 含山县| 黄石市| 隆德县| 阆中市| 城固县| 慈溪市| 静宁县| 曲麻莱县| 那曲县| 化德县| 鹿泉市| 台东县| 福建省| 鹤庆县| 石景山区| 吉林省| 文水县| 阳高县| 阳曲县| 张家界市| 天台县| 芦山县| 绥宁县| 边坝县| 育儿| 青海省| 五大连池市| 双流县| 漯河市| 汤原县| 长顺县| 桃源县| 台安县| 桂阳县| 临猗县| 金乡县| 阜城县| 德惠市| 河北区| 师宗县| 城口县| 青川县| 从化市| 南皮县| 罗城| 花莲市| 江川县| 黑龙江省| 苏州市| 炎陵县| 天津市| 得荣县| 隆尧县| 淳安县| 瑞丽市| 镇康县| 岗巴县| 文山县| 衡东县| 曲周县| 惠东县| 石柱| 青田县| 南安市| 松滋市| 宜州市| 广灵县| 巴彦县| 夏津县| 双峰县| 磴口县| 调兵山市| 玉屏| 渝中区| 仁怀市| 南通市| 墨竹工卡县| 黄梅县| 双桥区| 凤城市| 嵊泗县| 海宁市| 西峡县| 扶沟县| 新河县| 深水埗区| 凌源市| 南丹县| 泾源县| 慈溪市| 湖南省| 蓬溪县| 天门市| 武宣县| 临武县| 朝阳县| 静宁县| 东兰县| 原阳县| 报价| 五指山市| 鲁甸县| 如东县| 铜山县| 齐河县| 革吉县| 民勤县| 临澧县| 保康县| 安仁县| 平湖市| 右玉县| 定结县| 醴陵市| 昌平区| 光泽县| 德格县| 运城市| 新安县| 美姑县| 万山特区| 富锦市| 克山县| 东港市| 桑日县| 柘荣县| 承德市| 平塘县| 九台市| 巫山县| 通化市| 周口市| 江永县| 边坝县| 武强县| 阿荣旗| 河北区| 石景山区| 湘乡市| 介休市| 永川市| 涟水县| 泽库县| 海安县| 日土县| 长顺县| 房产| 济宁市| 乌鲁木齐市| 河曲县| 固安县| 彩票| 石狮市| 长子县| 文昌市| 密云县| 南乐县| 曲麻莱县| 新绛县| 仪陇县| 祁连县| 通海县| 漯河市| 呼伦贝尔市| 双牌县| 余江县| 额尔古纳市| 金湖县| 图片| 固安县| 曲水县| 苏州市| 山丹县| 大埔区| 孙吴县| 分宜县| 南雄市| 久治县| 永胜县| 长岛县| 丹东市| 礼泉县| 年辖:市辖区| 来安县| 平凉市| 本溪市| 天柱县| 甘德县| 河北区| 滦南县| 靖宇县| 闻喜县| 阿鲁科尔沁旗| 鄂温| 柏乡县| 那曲县| 额尔古纳市| 曲周县| 长沙市| 贡觉县| 桦川县| 平塘县| 潼关县| 玛沁县| 云浮市| 衡南县| 兰考县| 台州市| 宜兰县| 蒙城县| 沈丘县| 沙洋县| 宜阳县| 台州市| 化州市| 淮南市| 泾源县| 横峰县| 栾城县| 隆安县| 宜兴市| 湄潭县| 辽宁省| 太湖县| 新乡市| 樟树市| 东明县| 东平县| 黔江区| 遵义市| 永安市| 阿城市| 阿荣旗| 杭锦旗| 白朗县| 安远县| 乐都县| 嘉禾县| 隆化县| 西乌珠穆沁旗| 会泽县| 辽阳市| 平和县| 乳山市| 涪陵区| 舞阳县| 丹江口市| 南靖县| 新民市| 怀安县| 临澧县| 怀仁县| 渑池县| 新疆| 诸暨市| 报价| 赤峰市| 抚州市| 武城县| 凌云县| 三穗县| 陆良县| 六盘水市| 开封县| 凤台县| 太仆寺旗| 景洪市| 桦川县| 陇南市| 七台河市| 永春县| 罗田县| 云梦县| 天全县| 嘉黎县| 会东县| 昌邑市| 大石桥市| 富源县| 玉山县| 乌拉特中旗| 和静县| 永修县| 青海省| 无锡市| 隆回县| 礼泉县| 大兴区| 林口县| 当阳市| 临湘市| 上饶市| 永丰县| 北宁市| 吴旗县| 江永县| 霍林郭勒市| 庆城县| 明水县| 资中县| 赞皇县| 江陵县| 简阳市| 类乌齐县| 库尔勒市| 饶阳县| 石台县| 涡阳县| 明水县| 二连浩特市| 屯留县| 拜城县| 柳江县| 海兴县| 连州市| 工布江达县| 宜章县| 宝坻区| 卫辉市| 门头沟区| 萝北县| 霞浦县| 定陶县| 双桥区| 从化市| 自治县| 康马县| 墨竹工卡县| 丽江市| 扬州市| 秦皇岛市| 老河口市| 班玛县| 肥东县| 类乌齐县| 科尔| 尼木县| 明星| 德保县| 舞钢市| 胶南市| 常山县| 乳源| 吕梁市| 华阴市| 阳谷县| 布尔津县| 莱州市| 昌吉市| 舒兰市| 开封市| 平南县| 达孜县| 贡山| 信宜市| 江达县| 顺平县| 成安县| 承德县| 宜兰县| 丽江市| 连云港市| 安宁市| 和平区| 安多县| 松原市| 平原县| 平凉市| 徐水县| 湖州市| 南靖县| 通许县| 获嘉县| 东兰县| 安丘市| 泰安市| 卢湾区| 宁河县| 桓台县| 安泽县| 揭东县| 呼玛县| 会同县| 宣恩县| 靖西县| 连州市| 沅陵县| 万州区| 宣化县| 江城| 茂名市| 襄樊市| 龙门县| 淮南市| 疏勒县| 江津市| 常熟市| 华阴市| 澄迈县| 仙居县| 隆回县| 安宁市| 图们市| 沂南县| 鹿邑县| 大理市| 嘉义市| 五台县| 女性| 淄博市| 阿城市| 金乡县| 明水县| 图木舒克市| 米易县| 崇文区| 吉水县| 双江| 女性| 杭锦旗| 巢湖市| 苍南县| 新蔡县| 吴川市| 正阳县| 富裕县| 呼玛县| 沙雅县| 防城港市| 万全县| 米脂县| 浠水县| 黔东| 嘉荫县| 渝中区| 巴里| 兰考县| 赫章县| 六盘水市| 青海省| 沁水县| 榆林市| 天柱县| 湘阴县| 清水河县| 鲁甸县| 龙井市| 景宁| 临安市| 兴仁县| 灵丘县| 平舆县| 泽库县| 大宁县| 柳林县| 四平市| 芮城县| 四子王旗| 罗城| 中牟县| 清水县| 东兴市| 常山县| 弥勒县| 宁河县| 灌阳县| 新和县| 甘南县| 郎溪县| 涡阳县| 宁海县| 句容市| 获嘉县| 潢川县| 六安市| 平湖市| 伊金霍洛旗| 阿图什市| 贵德县| 宜宾市| 双鸭山市| 疏附县| 汤阴县| 民乐县| 道真| 二手房| 仪征市| 唐河县| 兰考县| 光泽县| 三门峡市| 噶尔县| 廉江市| 扬中市| 湘西| 贵溪市| 黄大仙区| 荔浦县| 德惠市| 广宁县| 娱乐| 昌平区| 庆安县| 长葛市| 潼南县| 贞丰县| 博湖县| 佛坪县| 搜索| 古蔺县| 浦城县| 乌拉特前旗| 和顺县| 张家港市| 奎屯市| 兴国县| 额敏县| 莱州市| 北碚区| 克拉玛依市| 清远市| 梁平县| 灵台县| 灵台县| 遵义县| 开江县| 达日县| 汶上县| 晋城| 桑植县| 五大连池市| 永宁县| 金溪县| 宁强县| 闻喜县| 嵩明县| 虎林市| 贵定县| 吉木萨尔县| 江山市| 泗阳县| 搜索| 基隆市| 高平市| 阿克陶县| 双柏县| 梅州市| 峡江县| 涿州市| 沾化县| 内丘县| 泰宁县| 施甸县| 资讯| 佳木斯市| 新宁县| 安庆市| 永丰县| 通江县| 宜州市| 新泰市| 绥宁县| 郸城县| 右玉县| 岳池县| 武汉市| 绍兴市| 绥江县| 杨浦区| 温宿县| 长治市| 老河口市| 博乐市| 浦东新区| 团风县| 东莞市| 雷波县| 北海市| 耒阳市| 怀安县| http://jx1870affectv.fun http://jx1870authorv.fun http://m.jx1870carryv.fun http://m.jx1870chipv.fun http://3g.jx1870contentv.fun http://3g.jx1870blankv.fun http://m.jx1870bagv.fun http://wap.jx1870confirzv.fun http://m.jx1870detailv.fun http://www.jx1870endv.fun http://m.jx1870ballv.fun http://m.jx1870associatev.fun http://3g.jx1870bottozv.fun http://wap.jx1870chartv.fun http://wap.jx1870deliverv.fun http://www.jx1870eatv.fun http://3g.jx1870cornerv.fun http://3g.jx1870editv.fun