zoukankan      html  css  js  c++  java
  • spring boot 迁移至asp.net core

    asp.net core类似于spring boot,内置了一个kerstral web服务器,所以可以直接通过dotnet启动,然后访问。

    本文着重于.net操作mongodb的过程

    框架添加mongoHelper

    因为EFcore是不支持mongoHelper,所以只能通过MongoClient来访问数据库

    首先框架中添加mongoHelper类,mongoHelper通过泛型来实现增删改查,数据库配置在appSetting.json中,然后把mongoHelper注入容器

    public static class MongoServiceCollectionExtension
        {
            public static void AddMongoDb(this IServiceCollection services, IConfiguration configuration)
            {
                services.Configure<MongoOption>(configuration.GetSection("MongoOption"));
    
                services.AddSingleton<MongoClientHelper>();
                services.AddSingleton<MongoHelper>();
            }
        }
    public class MongoHelper
        {
            private IMongoDatabase _dataBase;
    
            private MongoClient _client;
    
            public MongoHelper(MongoClientHelper clienthelper, IOptions<MongoOption> option)
            {
                _client = clienthelper.GetMongoClient();
                _dataBase = _client.GetDatabase(option.Value.DefaultDataBase);
            }
    
            public void SwitchDataBase(string dataBaseName)
            {
                _dataBase = _client.GetDatabase(dataBaseName);
            }
    
            private IMongoCollection<T> GetCollection<T>()
            {
                return _dataBase.GetCollection<T>(typeof(T).Name);
            }
            private IMongoCollection<BsonDocument> GetAggregrationCollection<T>()
            {
                return _dataBase.GetCollection<BsonDocument>(typeof(T).Name);
            }
    }

    下面来详细说说遇到的坑

    1. 获取不到配置的database

    一开始的配置如下,然后发现最后获取的database是默认的admin,并不是配置的mydb

    // mongoDb配置
      "MongoOption": {
        "MongoHost": "mongodb://me:123456@127.0.0.1:27017",
        "DefaultDataBase": "mydb"
      },

    网上查到一句话

     最终把db名字加到了后面

    // mongoDb配置
      "MongoOption": {
        "MongoHost": "mongodb://me:123456@127.0.0.1:27017/mydb",
      },

    2. 读取表数据报错,不能将string转换成DateTime

    由于mongo的特性,不管我插入什么数据都行,只要把对应的model改成你想要的就行。但是读取的时候我们必须指定一个model,那么假如这个model以前插入过数据,然后被修改了又插入过数据,当你读取的时候就会报错。我这边有个字段原来是string类型的,用了一段时间后,被改成了DateTime类型。当我使用mongo的find方法时,他就报错了string不能转换成datetime。

    然后我尝试着增加构造函数,或者修改setter方法,但是依然没有用

    于是我在mongo里面增加了一个方法,可以看到上图中有2个GetCollection方法,第二个是给聚合函数用的,

            /// <summary>
            /// 根据条件查询数据
            /// </summary>
            public List<T> Get<T>(FilterDefinition<T> filter)
            {
                return GetCollection<T>().Find(filter).ToList();
            }
    
            /// <summary>
            /// 聚合查询表T
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="pipeline"></param>
            /// <returns></returns>
            public async Task<List<BsonDocument>> AggregateAsync<T>(PipelineDefinition<BsonDocument, BsonDocument> pipeline)
            {
                return (await GetAggregrationCollection<T>().AggregateAsync(pipeline)).ToList();
            }

    第二个查找出来的是BsonDocument类型的list,需要转换成对应的model list

        protected List<TaskCats> ConvertAggregateResultToTaskCats(List<BsonDocument> queryResults)
            {
                if (!queryResults.Any())
                    return null;
                return queryResults.Select(result =>
                {
                    // 历史遗留问题,reportingTime可能为空,为string,为datetime
                    //var reportingTime = result["reportingTime"];
                    var reportingTime = result.GetValue("reportingTime");
                    return new TaskCats(
                        result["adAccount"].ToString(),
                        Convert.ToDateTime(result["reportedDate"]),
                        reportingTime.ToString() == "BsonNull" ? Convert.ToDateTime("1990-11-11") : Convert.ToDateTime(reportingTime),
                        Convert.ToDateTime(result["startDate"]),
                        result["taskId"].ToString(),
                        result.GetValue("description", null)?.ToString(),
                        result.GetValue("weekday", null)?.ToString(),
                        Convert.ToDouble(result["workingHours"]),
                        result.GetValue("BUName", null)?.ToString(),
                        result.GetValue("priority", null)?.ToString(),
                        result.GetValue("projectName", null)?.ToString(),
                        result.GetValue("otherProject", null)?.ToString(),
                        result["_id"].ToString());
                }).ToList();
            }

    框架到此为止(最后那个转换是在业务层实现,因为会涉及到具体的entity)

    业务类实现

    controller实现交互,service负责具体的操作,联动model和entity以及dao层的mongoHelper。

    这里有一个前期数据导入的类,比如说导入初始管理员以及menu列表,这一块是跟业务相关的,我把它放在了业务层。

    编写IHost的extension类,通过IServiceScope获取注入的类对象,实现数据库插入

            /// <summary>
            /// Initialize the mongodb data, insert menu info and admin user.
            /// </summary>
            /// <param name="host">The host</param>
            public static void InitialData(this IHost host)
            {
                using var serviceScope = host.Services.CreateScope();
                var mongoHelper = serviceScope.ServiceProvider.GetRequiredService<MongoHelper>();
                AddMenuInfo(mongoHelper);
                if (!IsDefaultUserExsit(mongoHelper))
                {
                    AddDefaultUser(mongoHelper);
                }
            }    

    配置validation

    使用FluentValidation:https://www.cnblogs.com/lwqlun/p/10311945.html

    返回badRequest跟controller格式一致

     

     

     这个Extension是属于框架类,这边只是展示用

     

    一些问题

    1. 因为spring boot默认会给表增加_class字段用于映射,但是.net使用mongoClient并不需要这个字段,假如不定义就会报错。暂时没有找到很好的解决办法,定义了一个_class属性。

    2. 对于Nlog,路径一定要用/,不能用. 因为linux下会找不到路径,导致所有的log都记录在根目录下面

     3. MongoDb时区问题

    [BsonDateTimeOptions(Kind = DateTimeKind.Local)]

    很多攻略说添加这个特性,其实这个特性的意思是跟jvm设置一样的,插入的时候,mongo驱动会自动把时间转换成0时区的时间,存入数据库,然后你会发现数据库中的数据跟实际的比对确实是少了8个小时。查询的时候,查出来的数据,mongo驱动会自动再加上8小时,所以你使用的时候就感觉不出有问题。假如你需要数据库里面存储的时间跟实际的一致,那么不管你插入还是查询都必须加8小时(对于mongo的insert和find是这样,但是aggregate方法不需要加)。

    
    
    
  • 相关阅读:
    java数组------数组基本使用和3中初始化方式
    java面向对象-------final关键字
    java面向对象------- 多态
    java面向对象------- 封装
    Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
    Android 音视频开发(四):使用 Camera API 采集视频数据
    音频 PCM 数据的采集和播放
    http协议的学习
    Kotlin入门学习笔记
    RxJava笔记
  • 原文地址:https://www.cnblogs.com/xiaojidanbai/p/14197557.html
Copyright © 2011-2022 走看看