分类目录.NetCore

Linq多表查询

var q1 = from orderitem in q2
                     join pd in _iProductDetailContract.Entities on   orderitem.ProductDetailId equals pd.Id
                     join pm in ProductMainContract.Entities on pd.ProductMainId equals pm.Id
                     join user in UserContract.Entities on pm.BuyerId equals user.Id
                     into orderItemBuyer
                     from user in orderItemBuyer.DefaultIfEmpty()
                     group new { orderitem.Price, orderitem.Num }
                     by new { orderitem.ProductDetailId, orderitem.Name, orderitem.Size, orderitem.Price, pm.AliasName, BuyerName = user.Name }
                     into g
                     orderby g.Sum(p => p.Num) descending
                     select new
                     {
                         ProductDetailId = g.Key.ProductDetailId,
                         Name = g.Key.Name,
                         Size = g.Key.Size,
                         AliasName = g.Key.AliasName,
                         BuyerName = g.Key.BuyerName,
                         Num = g.Sum(p => p.Num),
                         Price = g.Key.Price,
                         TotlePrice = g.Sum(p => p.Num * p.Price)
                     }
                     ;

Lambda和Linq三表连接查询加分组

三表连接查询加分组的方法

方法一:Lambda

方法二:Linq

数据库事例:

效果图:



.NetCore JWT认证

1、创建.net core web api项目:

Create a Web API with ASP.NET Core and Visual Studio

按照上面链接创建项目。

2、添加JWT(Bearer Token)认证

  • 在项目的Startup.cs文件中的ConfigureServices方法添加以下代码添加并配置JWT认证:
            //添加jwt验证:services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,//是否验证Issuer
            ValidateAudience = true,//是否验证Audience
            ValidateLifetime = true,//是否验证失效时间
            ValidateIssuerSigningKey = true,//是否验证SecurityKey
            ValidAudience = Configuration["audience"],//Audience
            ValidIssuer = Configuration["issuer"],//Issuer,这两项和签发jwt的设置一致
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"]))//拿到SecurityKey
        };
     });

其中 Configuration[“audience”]、Configuration[“issuer”]、Configuration[“SecurityKey”]为读取项目中appsettings.json文件中的自定义字符串。

appsettings.json文件:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "SecurityKey": "dd%88*377f6d&f£$£$#$%#$%#$FF33fssDG^!3",
  "issuer": "guetServer",
  "audience": "guetClient"
}
  • 在项目的Startup.cs文件中的Configure方法添加以下代码配置授权:
app.UseAuthentication();//配置授权
  • 签发JWT

首先自定义API连接返回的数据类型在项目的Models文件夹添加RestfulData类,新建类文件,对应命名空间里面定义三个类,代码如下:

    public class RestfulData
    {
        /// <summary>
        /// <![CDATA[错误码]]>
        /// </summary>
        public int code { get; set; }

        /// <summary>
        ///<![CDATA[消息]]>
        /// </summary>
        public string message { get; set; }

        /// <summary>
        /// <![CDATA[相关的链接帮助地址]]>
        /// </summary>
        public string url { get; set; }

    }

    /// <summary>
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class RestfulData<T> : RestfulData
    {
        /// <summary>
        /// <![CDATA[数据]]>
        /// </summary>
        public virtual T data { get; set; }
    }

    /// <summary>
    /// <![CDATA[返回数组]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class RestfulArray<T> : RestfulData<IEnumerable<T>>
    {

    }

在项目中Models文件夹新建TokenObj类,代码如下

    public class TokenObj
    {
        public string token { get; set; }//token内容

        public long expires { get; set; }//过期时间
    }

做好以上准备之后在项目的Controllers文件夹里面新建一个API控制器类,如下图:

命名为OAuthController.cs。

将里面的方法全部删除,添加入以下代码

        private readonly IConfiguration _configuration;
  
        public OAuthController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        /// <summary>
        /// <![CDATA[获取访问令牌]]>
        /// </summary>
        /// <param name="user"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<RestfulData<TokenObj>> Token(string user, string password)//同步方法
        {
            var result = new RestfulData<TokenObj>();
            try
            {
                if (string.IsNullOrEmpty(user)) throw new ArgumentNullException("user", "用户名不能为空!");
                if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password", "密码不能为空!");

                //验证数据库用户名和密码
                //var userInfo = await _UserService.CheckUserAndPassword(user,  password);
                var claims = new Claim[]
                {
                    new Claim(ClaimTypes.Name,user),
                    new Claim(ClaimTypes.NameIdentifier,password),
                };

                var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_configuration["SecurityKey"]));
                var expires = DateTime.Now.AddDays(30);//
                var token = new JwtSecurityToken(
                            issuer: _configuration["issuer"],
                            audience: _configuration["audience"],
                            claims: claims,
                            notBefore: DateTime.Now,
                            expires: expires,
                            signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256));

                //生成Token
                string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
                result.code = 200;
                result.data = new TokenObj() { token = jwtToken, expires = expires.ToFileTimeUtc() };
                result.message = "授权成功!";
                return result;
            }
            catch (Exception ex)
            {
                result.message = ex.Message;
                result.code = 400;
                // logger.Error("获取访问令牌时发生错误!", ex);
                return result;
            }
        }

下面添加Swagger UI并验证JWT认证。

3、添加Swashbuckle

Get started with Swashbuckle and ASP.NET Core

按照上面链接添加Swagger UI

  • 在Swagger中添加JWT认证功能

在startup.cs文件中的ConfigureServices方法中的services.AddSwaggerGen配置末尾添加以下代码

                c.AddSecurityDefinition("Bearer", 
                    new ApiKeyScheme {
                        In = "header",
                        Description = "请输入OAuth接口返回的Token,前置Bearer。示例:Bearer {Roken}",
                        Name = "Authorization",
                        Type = "apiKey"
                    });
                c.AddSecurityRequirement(
                    new Dictionary<string, IEnumerable<string>>
                    {
                        { "Bearer",
                          Enumerable.Empty<string>()
                        },
                    });

4、调试

在项目内置的ValuesController中给Get方法添加[Authorize]标签,如下图所示:

调试项目,进入Swagger UI页面,url为http://localhost:<port>/swagger进行调试。

直接请求GET  /api/Values

点击Try it out,再点Execute可见Server response的code是401,未授权: (Unauthorized)

我们尝试OAuth接口获取Token,user password随便输入,可以看到返回的数据有一个token。我们将它复制备用。

点击页面上端的Authorize按钮,按如下图格式输入我们刚刚复制的token,前面带有Bearer,与复制的token间隔一个空格。

再点击Authorize按钮,关闭对话框,然后再去尝试GET  /api/Values接口吧!

返回结果正确,DONE!!!!

生成的token超长,尚未知道如何刷新token。

 

EF Core通用基础类

using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Sys.Reponsitory;
using Sys.Reponsitory.Core;
using Sys.Reponsitory.Interface;
using Z.EntityFramework.Plus;

namespace Sys.Reponsitory
{
    public class BaseReponsitory<T> : IReponsitory<T> where T : Entity
    {
        private SysDbContext _context;

        public BaseReponsitory(SysDbContext context)
        {
            _context = context;
        }


        /// <summary>
        /// 根据过滤条件,获取记录
        /// </summary>
        /// <param name="exp">The exp.</param>
        public IQueryable<T> Find(Expression<Func<T, bool>> exp = null)
        {
            return Filter(exp);
        }

        public bool IsExist(Expression<Func<T, bool>> exp)
        {
            return _context.Set<T>().Any(exp);
        }

        /// <summary>
        /// 查找单个,且不被上下文所跟踪
        /// </summary>
        public T FindSingle(Expression<Func<T, bool>> exp)
        {
            return _context.Set<T>().AsNoTracking().FirstOrDefault(exp);
        }

        /// <summary>
        /// 得到分页记录
        /// </summary>
        /// <param name="pageindex">The pageindex.</param>
        /// <param name="pagesize">The pagesize.</param>
        /// <param name="orderby">排序</param>
        public IQueryable<T> Find<S>(int pageindex, int pagesize, Expression<Func<T, S>> orderByLambda, Expression<Func<T, bool>> exp = null)
        {
            if (pageindex < 1)
                pageindex = 1;

            return Filter(exp).OrderBy(orderByLambda).Skip(pagesize * (pageindex - 1)).Take(pagesize);
        }

        /// <summary>
        /// 根据过滤条件获取记录数
        /// </summary>
        public int GetCount(Expression<Func<T, bool>> exp = null)
        {
            return Filter(exp).Count();
        }

        public void Add(T entity)
        {
            if (string.IsNullOrEmpty(entity.Id))
            {
                entity.Id = Guid.NewGuid().ToString();
            }
            _context.Set<T>().Add(entity);
            Save();
            _context.Entry(entity).State = EntityState.Detached;
        }

        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="entities">The entities.</param>
        public void BatchAdd(T[] entities)
        {
            foreach (var entity in entities)
            {
                entity.Id = Guid.NewGuid().ToString();
            }
            _context.Set<T>().AddRange(entities);
            Save();
        }

        public void Update(T entity)
        {
            var entry = this._context.Entry(entity);
            entry.State = EntityState.Modified;
            foreach (System.Reflection.PropertyInfo p in entity.GetType().GetProperties())
            {
                string type = p.PropertyType.Name.ToString();
                if (p.Name == type)
                {
                    continue;
                }
                if (p.GetValue(entity) == null)
                {
                    if (this._context.Entry(entity).Property(p.Name).IsModified)
                    {
                        this._context.Entry(entity).Property(p.Name).IsModified = false;
                    }

                }
            }

            //如果数据没有发生变化
            if (!this._context.ChangeTracker.HasChanges())
            {
                return;
            }

            Save();
        }

        public void Delete(T entity)
        {
            _context.Set<T>().Remove(entity);
            Save();
        }


        /// <summary>
        /// 实现按需要只更新部分更新
        /// <para>如:Update(u =>u.Id==1,u =>new User{Name="ok"});</para>
        /// </summary>
        /// <param name="where">The where.</param>
        /// <param name="entity">The entity.</param>
        public void Update(Expression<Func<T, bool>> where, Expression<Func<T, T>> entity)
        {
            _context.Set<T>().Where(where).Update(entity);
        }

        public virtual void Delete(Expression<Func<T, bool>> exp)
        {
            _context.Set<T>().Where(exp).Delete();
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        private IQueryable<T> Filter(Expression<Func<T, bool>> exp)
        {
            var dbSet = _context.Set<T>().AsNoTracking().AsQueryable();
            if (exp != null)
                dbSet = dbSet.Where(exp);
            return dbSet;
        }

        public int ExecuteSql(string sql)
        {
            return _context.Database.ExecuteSqlCommand(sql);
        }
    }
}