上次的日记中已经提前预告了将要介绍的内容,在本次日记中我将介绍Entity Framework Code First如何处理类之间的继承关系。Entity Framework Code First有三种处理类之间继承关系的方法,我们将逐一介绍这三种处理方法。
1.Table Per Hierarchy(TPH): 只建立一个表,把基类和子类中的所有属性都映射为表中的列。
2.Table Per Type(TPT): 为基类和每个子类建立一个表,每个与子类对应的表中只包含子类特有的属性对应的列。
3.Table Per Concrete Type(TPC):为每个子类建立一个表,每个与子类对应的表中包含基类的属性对应的列和子类特有属性对应的列。
1.Table Per Hierarchy(TPH)
在这种处理方式中,Entity Framework Code First为基类和所有子类建立一个表,基类和子类中的所有属性都映射为表中的一个列。Entity Framework Code First默认在这个表中建立一个叫做Discriminator的列,类型是nvarchar,长度是128。Entity Framework Code First会在存储基类或子类的时候,把类名作为Discriminator列的值。
在我们前面的示例程序中,由于我们要记录订单是被谁创建的,以及是被谁批准的,我们新增了一个SalesPerson类。
public class SalesPerson{
public string EmployeeID { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public DateTime HiredDate { get; set; }
}.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
并且在Order类中增加了两个SalesPerson的实例用于记录订单的创建人和批准人。
public SalesPerson CreatedBy { get; set; }public SalesPerson ApprovedBy { get; set; }.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
我们后来细化了我们的业务流程:订单是由销售员创建的;当客户要求的订单折扣过高时,需要销售经理的审批;经理每个月都有固定的折扣审批总额。销售员和销售经理都属于销售人员。这是一个典型的继承关系。
根据我们细化之后的业务流程,我们创建了两个新的类, SalesMan和SalesManager
public class SalesMan : SalesPerson{
public decimal DiscountLimit { get; set; }
}
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
public class SalesManager : SalesPerson{
public decimal DiscountAmountPerMonth { get; set; }
}.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
由于创建订单的时候涉及到了复杂的业务逻辑,需要为订单指定Customer和SalesMan, 我们新建了一个factory类用于创建订单。
public static class OrderFactory{
public static Order CreateNewOrder(Customer customer, SalesMan createUser)
{
Order order = new Order();
order.Customer = customer;
order.CreatedDate = DateTime.Now;
order.CreatedBy = createUser;
order.ApprovedBy = null;
return order;
}
}.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
我们新建一个单元测试方法用于测试我们新的销售人员继承关系以及新的订单factory类。
[TestMethod]
public void CanAddOrderWithSalesMan()
{
OrderSystemContext unitOfWork = new OrderSystemContext();
ProductRepository productRepository = new ProductRepository(unitOfWork);
OrderRepository orderRepository = new OrderRepository(unitOfWork);
CustomerRepository customerRepository = new CustomerRepository(unitOfWork);
SalesMan salesman = new SalesMan { EmployeeID = "2012001", Gender = "M", Name = "Eric", HiredDate = DateTime.Parse("2010-5-19") };
Customer customer = customerRepository.GetCustomerById("120104198403082113");
Order order = OrderFactory.CreateNewOrder(customer, salesman);
order.AddNewOrderItem(productRepository.GetProductCatalogById(1).GetProductInStock(), 5100);
orderRepository.AddNewOrder(order);
unitOfWork.CommitChanges();
}.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
执行完我们的测试程序之后,我们可以打开SQL Server去看一下Code First默认情况下是如何处理类之间的继承关系的。
Code First默认会把基类和子类的所有属性都映射成一个表中的列,并且会增加一个Discriminator列标识存进去的是哪个类的实例。
注意:这里的跨域指不到同一域名下,包括一级与二级域名,这里也认为不在同域下
从A网站把信息以Post的方式发送到B网站,这种过程叫做跨域POST,相类的,A网站把B网站的信息获取回来,一般称为跨域GET请求,而对于后者可以通过异步方式实现,在jq里封装了jsonp,用它来实现异步跨域请求;而异步跨域POST是不可以被实现的,下面我们通过实例来说明。
一 异步跨域
JS代码用来实现跨域GET和跨域POST,代码如下:(从www.post.com域名下访问二级域成file.post.com)
$.ajax({
type: "GET",
dataType: "jsonp",
url: "http://file.post.com/Home/GetInfo",
success: function (data) {
alert(data);
}
})
$("#btnsubmit").click(function () {
alert("操作...");
$.ajax({
type: "POST",
url: "http://file.post.com/home/create2",
data: { commentTitle: $("#CommentTitle").val(), commentInfo: $("#CommentInfo").val() },
success: function (data) {
alert(data);
}
})
});
</script>
表单如下:
<legend>Product_Comment</legend>
<div >
@Html.LabelFor(model => model.ProductID)
</div>
<div >
@Html.EditorFor(model => model.ProductID)
@Html.ValidationMessageFor(model => model.ProductID)
</div>
<div >
@Html.LabelFor(model => model.UserID)
</div>
<div >
@Html.EditorFor(model => model.UserID)
@Html.ValidationMessageFor(model => model.UserID)
</div>
<div >
@Html.LabelFor(model => model.CommentTitle)
</div>
<div >
@Html.EditorFor(model => model.CommentTitle)
@Html.ValidationMessageFor(model => model.CommentTitle)
</div>
<div >
@Html.LabelFor(model => model.CommentInfo)
</div>
<div >
@Html.EditorFor(model => model.CommentInfo)
@Html.ValidationMessageFor(model => model.CommentInfo)
</div>
<p>
<input type="button" value="Create" id="btnsubmit" />
</p>
</fieldset>
当加载页面后,通过firebug可以看到,使用jsonp的GET请求,返回了正确的信息:
而请求异步表单提交后,数据库里并没有记录,就是说异步不支持跨域POST
二 同步跨域
我们将表单按钮类型改为submit,让表单同步提交到其它域中
通过实验表明,同步表单的POST操作是可以的,当然这是正常的,向淘宝的支付接口也是通过同步POST来实现的,呵呵!
数据库中的信息如下:
恩,现在您应该对跨域POST有一个明确的认识了吧,对于同步表单POST,没有任何问题,而异步的POST,则受到了限制,无论是二级域名还是其它域名都不能进行POST请求的!
感谢您的阅读!
本文链接
get即通过URL中的QueryString向服务器端传值的方式,它的数据是可见的,可post则是通过一个postdata包向服务器传值,post方式可以传送更多数据(如上传文件),也更安全(如登录)。
本文将演示各种通过客户端页面(即最终生成的页面)向Controller提交请求以及在Controller中接受的方式。
约定
本文所有的示例都将是演示一个登录过程,但并不关注判断过程,所以判断方面仅做简单的IF操作。
而提交的实体我们新建一个Account类。
它的内容如下:
/// 用户账户的实体类
/// </summary>
public class Account {
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
}
文中大多数示例使用了Account类,但并不是所有的示例都使用了Account。
在文中我们并不关注提交信息的页面的Controller,仅关注处理信息的Controller。
而Controller中存在这样一个方法,用于辅助判断:
/// 一个辅助判断的方法
/// </summary>
/// <param name="userName">用户名</param>
/// <param name="password">密码</param>
/// <returns></returns>
string AreEquals(string userName,string password)
{
return (userName.ToLower() == "admin" && password == "123456").ToString();
}
以Post提交的数据来看传递
之所以这里先说Post是因为相对于Get方式来说Post的情况更全,说明了Post的情况Get也就差不多了。
View:
<p>
<label>用户名:</label>@Html.TextBox("username") </p>
<p>
<label>密码:</label>@Html.TextBox("password") </p>
<p>
<input type="submit" /></p>
}
1.从最基本的开始,使用Request获取提交的信息
2: /// 处理请求的Action
3: /// </summary>
4: /// <returns></returns>
5: public ActionResult Process()
6: {
7: return Content(
8: AreEquals(Request.Form["username"], Request.Form["password"])
9: );
10: }
这个无多解释,通过Request.Form来获取表单提交我想是最基本的方法之一,如果您对这种方法不了解的话,那么就说明您的ASP.NET基础有待提交,可以查看ASP.NET五大对象的相关文章。
2.通过Action参数提交
相比之下这个可能更加漂亮些。
2: /// 处理请求的Action
3: /// </summary>
4: /// <param name="userName">这两个参数务必与表单中的名称一致</param>
5: /// <param name="password"></param>
6: /// <returns></returns>
7: public ActionResult Process(string userName, string password)
8: {
9: return