WebApi+Html+EF+MySql

1、创建WepApi工程 编译工具VS2017

image

2、选择模板,配置生成参数,如下图

image

3、创建完工程后,创建一个默认控制器测试。

image
image
image

4、新建两个控制器路由函数(测试用),一个带参数,一个不带参数

image

5、配置服务跨域访问-有两种方法
方法一:代码配置
5.1 安装跨域所需DLL

image

5.2 打开WebApiConfig.cs文件,作如下配置,三个*号表示允许所有访问,只做测试,后期再根据需要限制

image

方法二、在Web.config文件中进行配置,加入如下配置就行了

 <system.webServer>
    <httpProtocol>
         <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
             <add name="Access-Control-Allow-Methods" value="HEAD, GET, POST, PUT, PATCH, DELETE,OPTIONS" />
            <add name="Access-Control-Allow-Headers" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

启动编译服务程序,获取自动分配端口号

image

PS:两种配置只能配置其中一种,不能同时配置,调试时还报错,请确认返回数据结构中是否有异常数据

6、编写前端测试文件,用的HBuilder X编写,用ajax访问
6.1 引入js文件

<script src="https://libs.baidu.com/jquery/1.10.2/jquery.min.js"></script>
6.2 编写ajax访问语句
<script>
$.ajax({
url: encodeURI('http://localhost:14464/api/testsend1'),
data: { "": "ids" },
dataType: 'json',   
crossDomain: true,
async: true,
success: function (data) {
console.log(data);
},
error: function(data) {
console.log(data);
}
})
</script>

6.3 启动调试网页,返回结果ok1,则代表测试成功--注意,调试时 HBuilder X与visual2017均以管理员权限启动

image

7、EF数据库使用,用的是三种方式中的code first方式,数据库采用mysql
7.1 新建models层类库

image

7.2 安装EntityFramework

image

7.3 安装MYSQL支持包-依赖项:FrameWork >=4.5.2

image

7.4 新建DbContext上下文文件

image

7.5 激活Migration的使用
7.5.1 通过 Tools->Nuget Package Manager->Package Manager Console 打开Package Manager Console窗口
7.5.2 Default project选择当前的DbContext所在的项目
7.5.3 通过命令开启Migration:Enable-Migrations

image

7.5.4 启用后会多出一个Migrations文件夹,文件夹底下有一个Configuration.cs配置文件
7.6 打开这个文件配置数据库自动迁移功能

image

7.7 打开之前新建的上下文文件,做如下配置,配置自动迁移功能

image

7.8 新建一个数据model基类BaseEntity

image

7.9 新建一个User类,继承model基类

image

7.10 BaseContext数据库上下文里添加public DbSet<User> Users { get; set; }--这句实现生成数据库时就自动创建了user表

image

7.10 Model类库工程app.config配置文件添下连接字符串和指定MySql连接方式,服务ip和数据库密码根据实际填写

<connectionStrings>
 <add name="MySqlConnectionString" connectionString="server=192.168.1.69;port=3306;database=tes_ttt;uid=sa;password=123456" providerName="MySql.Data.MySqlClient"/>
</connectionStrings>

  <system.data>
     <DbProviderFactories>
        <remove invariant="MySql.Data.MySqlClient" />
        <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL"     type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.10.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </DbProviderFactories>
 </system.data>

7.11 在单元测试工程安装7.2和7.3步骤的SQL数据库支持库,同时app.config配置文件也添加7.10的两个配置

7.12 新建测试创建数据库,如下图

image

7.13 执行测试后就生成了数据库

image

8、表数据创建与MySql运用
8.1 创建数据访问层DAL类库,引用Models类库
8.2 创建服务基类BaseService

namespace MyWebApiDemo.DAL
{
    /// <summary>
    /// 服务基类  所有数据服务从这里派生
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    public class BaseService<T> : IDisposable where T : BaseEntity, new()
    {
        #region 私有成员

        protected readonly BaseContext _db;

        #endregion 私有成员

        #region 构造与释放

        public BaseService(BaseContext db)
        {
            _db = db;
            // 数据库日志重定向
        }

        ~BaseService()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true); //I am calling you from Dispose, it's safe
            GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
        }

        protected virtual void Dispose(bool disposing)
        {
            _db.Dispose();
        }

        #endregion 构造与释放

        #region 增删改

        /// <summary>
        /// 创建一个新的行
        /// </summary>
        /// <param name="t">实体对象</param>
        /// <param name="saved">是否马上保存到数据库</param>
        /// <returns></returns>
        public async Task CreateAsync(T t, bool saved = true)
        {
            _db.Set<T>().Add(t);
            if (saved)
                await SaveAsync(true);
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="t">修改对象</param>
        /// <param name="saved">是否保存</param>
        /// <returns></returns>
        public async Task EditAsync(T t, bool saved = true)
        {
            _db.Entry(t).State = EntityState.Modified;
            if (saved)
                await SaveAsync(false);
        }

        public async Task EditObjectAsync(T t, Action<T> changeAction, bool saved = true)
        {
            _db.Entry(t).State = EntityState.Unchanged;
            changeAction(t);
            if (saved)
                await SaveAsync(false);
        }

        public async Task EditObjectAsync(Guid id, Action<T> changeAction, bool saved = true)
        {
            T t = new T { Id = id };
            _db.Entry(t).State = EntityState.Unchanged;
            changeAction(t);
            if (saved)
                await SaveAsync(false);
        }

        /// <summary>
        /// 移除一条数据(IsRemoved=true)
        /// </summary>
        /// <param name="id">ID</param>
        /// <param name="saved">是否马上保存到数据库</param>
        /// <returns></returns>
        public async Task RemoveAsync(Guid id, bool saved = true)
        {
            var t = new T()
            {
                Id = id
            };
            _db.Entry(t).State = EntityState.Unchanged;
            t.IsRemoved = true;
            if (saved)
                await SaveAsync(false);
        }

        #endregion 增删改

        #region 查询

        /// <summary>
        /// 获取所有对象
        /// </summary>
        /// <returns></returns>
        public IQueryable<T> GetAll()
        {
            return _db.Set<T>().AsNoTracking().Where(m => !m.IsRemoved);
        }

        /// <summary>
        /// 按指定条件获取所有对象
        /// </summary>
        /// <param name="predicate">条件谓词</param>
        /// <returns></returns>
        //public IQueryable<T> GetAll(Expression<Func<T, bool>> predicate)
        //{
        //    return GetAll().Where(predicate);
        //}

        /// <summary>
        /// 按指定条件和指定顺序获取所有对象,排序依据是创建时间
        /// </summary>
        /// <param name="predicate">条件谓词</param>
        /// <param name="asc">是否升序</param>
        /// <returns></returns>
        public IQueryable<T> GetAll(Expression<Func<T, bool>> predicate, bool asc = true)
        {
            var data = GetAll().Where(predicate);
            if (asc)
                return data.OrderBy(m => m.CreateTime);
            else
                return data.OrderByDescending(m => m.CreateTime);
        }

        /// <summary>
        /// 按照指定顺序以及指定分页获取全部
        /// </summary>
        /// <param name="asc">是否升序</param>
        /// <param name="pageIndex">分页下标</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public IQueryable<T> GetAll(bool asc, int pageIndex, int pageSize = 10)
        {
            if (asc)
                return GetAll().OrderBy(m => m.CreateTime)
                               .Skip(pageSize * pageIndex)
                               .Take(pageSize);
            else
                return GetAll().OrderByDescending(m => m.CreateTime)
                               .Skip(pageSize * pageIndex)
                               .Take(pageSize);
        }

        /// <summary>
        /// 按照指定条件和指定顺序以及指定分页获取全部
        /// </summary>
        /// <param name="predicate">条件谓词</param>
        /// <param name="asc">是否升序</param>
        /// <param name="pageIndex">分页下标</param>
        /// <param name="pageSize">分页大小</param>
        /// <returns></returns>
        public IQueryable<T> GetAll(Expression<Func<T, bool>> predicate, bool asc, int pageIndex, int pageSize = 10)
        {
            return GetAll(predicate, asc).Skip(pageSize * pageIndex).Take(pageSize);
        }

        /// <summary>
        /// 按照ID获取一条数据(如果未找到,则返回null)
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns></returns>
        public async Task<T> GetOne(Guid id)
        {
            return await GetAll().FirstOrDefaultAsync(m => m.Id == id);
        }

        #endregion 查询

        #region 保存

        /// <summary>
        /// 马上保存到数据库
        /// </summary>
        /// <param name="isValidate">是否校验数据(默认是)</param>
        /// <returns></returns>
        public async Task SaveAsync(bool isValidate = true)
        {
            if (isValidate)
            {
                await _db.SaveChangesAsync();
            }
            else
            {
                _db.Configuration.ValidateOnSaveEnabled = false;
                await _db.SaveChangesAsync();
                _db.Configuration.ValidateOnSaveEnabled = true;
            }
        }

        #endregion 保存
    }
}

8.3 创建用户服务类

namespace MyWebApiDemo.DAL
{
    public class UserService : BaseService<User>
    {
        public UserService(BaseContext db) : base(db)
        {
        }
    }
}

8.4 创建业务逻辑层BLL,引用DAL与Models


image.png

8.5 创建用户管理类-实现添加一个用户

namespace MyWebApiDemo.BLL
{
    public class UserManager
    {
        public static async Task<User> CreateUser(string account, string pwd, string name)
        {
            try
            {
                using (var db = new BaseContext())
                using (var userSvc = new UserService(db))
                {
                    User user = new User
                    {
                        LoginAccount = account,
                        Password = pwd,
                        UserName = name
                    };
                    await userSvc.CreateAsync(user);
                    return user;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
}

8.5 单元测试添加用户,测试成功后会在数据库user表中看到这个记录,如下图

        [TestMethod]
        public void TestAddOneUser()
        {
            try
            {
                UserManager.CreateUser("test001", "123456", "张三").Wait();
            }
            catch(Exception ex)
            {

            }
        }
image.png

至此,整个过程到此告一段落

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容