引言:
从第一开始,我就想,我们要想建一整套数据库,一个人来注册了,我们就可以给它注册一个库,这个库中所有的表结构,都是先前就准备好了的,我想,这个真的用EF的CodeFirst实现就最好了。因为我们的所有的ViewModel都是齐全的,用ModelFirst是需要画实体关联图的,用DBFirst就不用说了。
实现思路:
前期用我们所有的Model实体都是很好收集的,因为代码都是事先写好的,大概有100多个实体,这些实体就要满足;一旦有人进行注册,我们就给他生成这么多表的一个数据库。原理很简单,我们都知道EF实现这个的时候,用CodeFirst最合适不过了。
然后就是实现步骤,其实所有实现数据库连接和操作无非就是三步:连接、准备执行语句、执行。
其实用CodeFiist的这三步就是比ODBC进行了封装,使用户操作更加少的代码,只要写实体和Context(上下文)就可以了。实现起来比ODBC要简单的多。
我一开始一直以为EF是只读Web.config的,而我们都知道,Web.config文件的ConnectString节点是可以进行运行时的修改的,但是在我们修改了,但是问题出在Web.config只在系统开启的时候,才会加载出来。我试过了很多方法去解决web.config只在系统开启的时候加载这个问题,却忽略了一个真正能解决这个问题的方法:EF是不是只读Web.config?
这个问题还是江霄解决的,其实EF不是只读Web,config文件的。我们可以看看DbContext:
<span style="font-size:18px;">
public DbContext(string nameOrConnectionString);</span><span style="font-size:18px;">
</span>
DbContext是EF给我们封装的访问数据库的方法,我们可以看到DbContext中的参数是有两种的一种是name 一种是ConnectString,也就是说,我们可以传一个数据库的名称,也可以穿一个数据库连接字符串,这样我们就可以不用讲数据库连接字符串放在Web,cofig中了。
这个真心太棒了,我们在解决问题的时候,一定要思维很缜密,为一方面我们要多看看底层的封装,其实EF就是ODBC等底层的数据库连接进行了封装,所有我们看起来很高大上的东西,其实都是对最基本的东西进行封装形成的,很多东西其实都不是新的东西。
代码实现:
1、建库
这里我要将一个库,库中有两个表:
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace WebDemo.Models
{
[Serializable]
public class Student
{
[StringLength(32)]
public virtual string SName { get; set; }
[StringLength(32)]
public virtual string Address { get; set; }
[Key]
public virtual int Id { get; set; }
}
}</span>
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
namespace WebDemo.Models
{
[Serializable]
public class UserInfo
{
public string UName { get; set; }
[Required]
[MaxLength(32)]
public string UPwd { get; set; }
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
}
}</span>
现在我们创建DBContext:
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace WebDemo.Models
{
public class SchoolWoeDbContext :DbContext
{
public SchoolWoeDbContext(string ConncectionString)
: base(ConncectionString)
{
this.Database.CreateIfNotExists();
}
public virtual DbSet<Student> Student { get; set; }
public virtual DbSet<UserInfo> UserInfo { get; set; }
}
}</span>
我们访问的公共数据库:(因为我们要注册就生成一个库,首先我们要有自己的数据User表),因此我们建立自己的公共库,所有人只要注册或登录这个系统首先要进入这个库中:
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace WebDemo.Models
{
public class SchoolDbContext :DbContext
{
public SchoolDbContext()
: base("name=MySqlDemo")
{
this.Database.CreateIfNotExists();
}
public virtual DbSet<UserInfo> UserInfo { get; set; }
}
}</span>
建立好了,我们就用MVC进行前台的搭建:
我们首先建立LoginController:
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebDemo.Models;
namespace WebDemo.Controllers
{
public class LogonController : Controller
{
//
// GET: /Logon/
public ActionResult Index()
{
return View();
}
/// <summary>
/// 登陆信息
/// </summary>
/// <param name="user">User实体</param>
/// <returns></returns>
public ActionResult Login(UserInfo user)
{
SchoolDbContext dbContext =new SchoolDbContext(); //对公共数据库进行连接,查询是否该用户已经存在
var loginUser = dbContext.UserInfo.Where(u => u.UName.Equals(user.UName) && u.UPwd.Equals(user.UPwd)).FirstOrDefault();
if (loginUser == null)
{
return Content("用户名密码错误!");
}
else
{
Guid sessionId = Guid.NewGuid();//申请了一个模拟的GUID:SessionId
//把sessionid写到客户端浏览器里面去累
Response.Cookies["sessionId"].Value = sessionId.ToString();
//
MemcacheHelper.Set(sessionId.ToString(), loginUser, DateTime.Now.AddMinutes(20));
string connectionString = "Data Source=192.168.24.233;user id=sa;password=123456;persist security info=True;database=" + user.UName;//连接字符串
SchoolWoeDbContext dbContext1 = new SchoolWoeDbContext();
dbContext1.UserInfo.Add(user);
dbContext1.SaveChanges();
return Content("ok");
}
}
public ActionResult ValidateCode()
{
ValidateCodeHelper helper =new ValidateCodeHelper();
string strCode = helper.CreateValidateCode(4);
Session["validateCode"] = strCode;
var byteData = helper.CreateValidateGraphic(strCode);
return File(byteData, "image/jpeg");
}
}
}</span>
建立Index界面:
<span style="font-size:18px;">@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>ITOO后台管理系统登录</title>
<script src="../../Scripts/jquery-1.7.1.js"></script>
<script src="../../Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script type="text/javascript">
if (window.parent.window != window) {
window.top.location.href = "/Logon/Index";
}
function changeCheckCode() {
var newUrl = $("#img").attr("src") + 1;
$("#img").attr("src", newUrl);
}
function afterLogin(data) {
if (data != "ok") {
alert(data);
changeCheckCode();
} else {
window.location.href = "/Home/Index";
}
}
</script>
<style type="text/css">
*
{
padding: 0;
margin: 0;
}
body
{
text-align: center;
background: #4974A4;
}
#login
{
width: 740px;
margin: 0 auto;
font-size: 12px;
}
#loginlogo
{
width: 700px;
height: 100px;
overflow: hidden;
background: url('/Content/Images/login/logo.png') no-repeat;
margin-top: 50px;
}
#loginpanel
{
width: 729px;
position: relative;
height: 300px;
}
.panel-h
{
width: 729px;
height: 20px;
background: url('/Content/Images/login/panel-h.gif') no-repeat;
position: absolute;
top: 0px;
left: 0px;
z-index: 3;
}
.panel-f
{
width: 729px;
height: 13px;
background: url('/Content/Images/login/panel-f.gif') no-repeat;
position: absolute;
bottom: 0px;
left: 0px;
z-index: 3;
}
.panel-c
{
z-index: 2;
background: url('/Content/Images/login/panel-c.gif') repeat-y;
width: 729px;
height: 300px;
}
.panel-c-l
{
position: absolute;
left: 60px;
top: 40px;
}
.panel-c-r
{
position: absolute;
right: 20px;
top: 50px;
width: 222px;
line-height: 200%;
text-align: left;
}
.panel-c-l h3
{
color: #556A85;
margin-bottom: 10px;
}
.panel-c-l td
{
padding: 7px;
}
.login-text
{
height: 24px;
left: 24px;
border: 1px solid #e9e9e9;
background: #f9f9f9;
}
.login-text-focus
{
border: 1px solid #E6BF73;
}
.login-btn
{
width: 114px;
height: 29px;
color: #E9FFFF;
line-height: 29px;
background: url('/Content/Images/login/login-btn.gif') no-repeat;
border: none;
overflow: hidden;
cursor: pointer;
}
#txtUsername, #code, #txtPassword
{
width: 191px;
}
#logincopyright
{
text-align: center;
color: White;
margin-top: 50px;
}
a
{
color: Black;
}
a:hover
{
color: Red;
text-decoration: underline;
}
</style>
</head>
<body style="padding: 10px">
@using (Ajax.BeginForm("Login", "Logon", new AjaxOptions() { OnSuccess = "afterLogin" }))
{
<div id="login">
<div id="loginlogo">
</div>
<div id="loginpanel">
<div class="panel-h">
</div>
<div class="panel-c">
<div class="panel-c-l">
<table cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td align="left" colspan="2">
<h3>
请用ITOO后台管理系统账号登录</h3>
</td>
</tr>
<tr>
<td align="right">
账号:
</td>
<td align="left">
<input type="text" name="UName" value="admin" id="UName" class="login-text" />
</td>
</tr>
<tr>
<td align="right">
密码:
</td>
<td align="left">
<input type="password" name="UPwd" id="UPwd" value="123" class="login-text" />
</td>
</tr>
<tr>
<td>
验证码:
</td>
<td align="left">
<input type="text" class="login-text" id="code" name="vCode" value="1" />
</td>
</tr>
<tr>
<td>
</td>
<td>
<img id="img" οnclick="changeCheckCode()" src="/Logon/ValidateCode?id4=1" style="float: left; height: 24px;" />
<div style="float: left; margin-left: 5px; margin-top: 10px;">
<a href="javascript:void(0)" οnclick="changeCheckCode();return false;">看不清,换一张</a>
</div>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<input type="submit" id="btnLogin" value="登录" class="login-btn" />
</td>
</tr>
</tbody>
</table>
</div>
<div class="panel-c-r">
<p>
请从左侧输入登录账号和密码登录</p>
<p>
如果遇到系统问题,请联系网络管理员。</p>
<p>
如果没有账号,请联系网站管理员。
</p>
<p>
......</p>
</div>
</div>
<div class="panel-f">
</div>
</div>
<div id="logincopyright">
Copyright ? 2013 itcast.com
</div>
</div>
}
</body>
</html></span>
在配置文件中配置:
<span style="font-size:18px;"> <connectionStrings>
<add name="MySqlDemo" connectionString="Data Source=192.168.24.233;user id=sa;password=123456;persist security info=True;database=CutDb1"
providerName="System.Data.SqlClient" />
</connectionStrings></span>
这个是给公共数据库进行连接使用的,因为它的参数是string name的,name就要在Web.config中进行读取。
2、切库:
其实我们实现了动态建库,那么切库就会很简单,就是我们将用户注册的用户信息和他要访问的数据连接字符串存储在公共数据库表中的User表,这样该用户首先查到自己的数据库,然后我们再给他分配数据库。
总结:
我有很多时候都是这样的,当自己被一种想法束缚住的时候,我们可以和别人交流一下,或者换一个人去想这个问题,这个时候就是团队的力量。
我们在想问题的时候,一定要思维缜密,可能有时候你就会错过一些很重要的东西。
现在我们做的东西,用EF+MVC+EasyUI+WCF,其实这些东西都是我们一直用的东西继续封装后的东西,我们不要作为一种新的东西去学习,我们要多思考,多去想,很多东西其实就是我们都学习过的,很简单的。
解决问题的时候,我们一定要坚信,办法总比问题多!!!