Entity Framwork学习笔记

一、First Demo

 

 

 

 

EF从数据库生成模型步骤:

1.数据库里有一个UserInfo表:

 

2.右击Model文件夹 - 新建 - Ado.net数据模型:

3.

 

4.

5.

 

6.

 

7.

 

8.Modle文件夹会生成两个类文件:EFTest.cs是数据库上下文类文件。UserInfo是实体类。

数据库上下文类:

namespace EFTest.Models
{
    using System;
    using System.Data.Entity;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Linq;

    public partial class EFTest : DbContext
    {
        public EFTest()
            : base("name=MyContext")
        {
        }

        public virtual DbSet<UserInfo> UserInfo { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
    }
}
View Code

实体类:

namespace EFTest.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    [Table("UserInfo")]
    public partial class UserInfo
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }

        [StringLength(10)]
        public string Name { get; set; }

        public int? Age { get; set; }

        public DateTime? Birthday { get; set; }
    }
}
View Code

 

Web.config生成的连接字符串:

  <connectionStrings>
    <add name="MyContext" connectionString="data source=.;initial catalog=EFTest;user id=sa;password=123456;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
  </connectionStrings>

 

Controller中使用linq查询和Lambda方法两种方式进行查询:(可连接数据库进行测试Linq写法与Lambda方式的相互转换工具下载:LINQPad)   LINQPad使用教程>>

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using t2_EFTest.Models;

namespace t2_EFTest.Controllers
{
    public class UserInfoController : Controller
    {
        // GET: /UserInfo/
        public ActionResult Index()
        {
            //MyContext myContext=new MyContext();
            //查询语法
            //var list = from abc in myContext.UserInfo
            //               select abc;

            //方法语法
            //var list = myContext.UserInfo.Select(u => u);


            //建议:声明父类型的变量,指向子类型的对象 (面向多态的开始)
            //// DbSet<UserInfo> UserInfo { get; set; }
            //DbContext dbContext=new MyContext();
            ////DbSet<TEntity> Set<TEntity>()
            //dbContext.Set<UserInfo>();

IQueryable<UserInfo> list; //创建上下文对象 DbContext dbContext=new MyContext(); //基本查询 //list = from userInfo in dbContext.Set<UserInfo>() // select userInfo; //单条件查询 //list = from userInfo in dbContext.Set<UserInfo>() // where userInfo.Uid>2 // select userInfo; //多条件 //list = from userInfo in dbContext.Set<UserInfo>() // where userInfo.Uid > 2 && userInfo.UName.Length > 2 // select userInfo; //查询单列 //var list1 = from userInfo in dbContext.Set<UserInfo>() // select userInfo.Uid; //查询多列 //var list1 = from useriInfo in dbContext.Set<UserInfo>() // select new UserInfoViewModel() // { // Uid=useriInfo.Uid, // UName=useriInfo.UName // }; //分页 var list1 = from userInfo in dbContext.Set<UserInfo>() select userInfo; list1 = list1.OrderByDescending(u=>u.Uid).Skip(2).Take(3); //先排序,后取数据 分页是Lambda特有的
return View(list1); } public ActionResult Index2() { DbContext dbContext=new MyContext(); //基本查询 var list1 = dbContext.Set<UserInfo>(); IQueryable<UserInfo> list; //单条件 list = list1.Where(u => u.Uid > 2); //多条件 //list = list1.Where(u => (u.Uid > 2) || (u.UName.Contains("龙"))); //list = list1.Where(u => u.Uid > 2) // .Where(u => u.UName.Contains("龙")); //查询自定义列 //list = list1.select(u => new userinfoviewmodel() //展示部分列的话,可以新建一个model类字段为需要展示的字段 //{ // uid = u.uid, // uname = u.uname //}); return View(list); } } }

 

View中的显示:

Index:

@using t2_EFTest.Models
@*model IQueryable<t2_EFTest.Models.UserInfo>*@
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <table border="1">
            <tr>
                <th>编号</th>
                <th>姓名</th>
            </tr>
            @foreach (var userInfo in Model)
            {
                //var ui = userInfo as UserInfoViewModel;
            <tr>
                <td>@userInfo.Uid</td>
                <td>@userInfo.UName</td>
            </tr>
        }

        </table>
        
    </div>
</body>
</html>
View Code

Index2:

@model IQueryable<t2_EFTest.Models.UserInfo>
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index2</title>
</head>
<body>
    <div>
        <table border="1">
            <tr>
                <th>编号</th>
                <th>姓名</th>
            </tr>
            @foreach (var userInfo in Model)
            {
                <tr>
                    <td>@userInfo.Uid</td>
                    <td>@userInfo.UName</td>
                </tr>
            }
        </table>
    </div>
</body>
</html>
View Code

 

 

表NewsType与NewInfo必须建立外键关系才能生成导航属性:

生成的NewsInfo类:

namespace t2_EFTest.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class NewsInfo
    {
        public int nid { get; set; }
        public string nTitle { get; set; }
        public int nTid { get; set; }
    
        public virtual NewsType NewsType { get; set; }
    }
}

生成的NewsType类:

namespace t2_EFTest.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class NewsType
    {
        public NewsType()
        {
            this.NewsInfo = new HashSet<NewsInfo>();
        }
    
        public int tid { get; set; }
        public string tTitle { get; set; }
    
        public virtual ICollection<NewsInfo> NewsInfo { get; set; }
    }
}

 

导航属性Controller部分:

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using t2_EFTest.Models;

namespace t2_EFTest.Controllers
{
    public class NewsInfoController : Controller
    {
        // GET: /NewsInfo/
        public ActionResult Index()
        {
            DbContext dbContext=new MyContext();
            //var list = from newsInfo in dbContext.Set<NewsInfo>()
            //    join typeInfo in dbContext.Set<t2_EFTest.Models.NewsType>() on newsInfo.nTid equals typeInfo.tid
            //    select newsInfo
            //;

            //from后面的in一定要是一个集合类型的对象,才可以连接
            //var list = from newsType in dbContext.Set<NewsType>()
            //    from newsInfo in newsType.NewsInfo
            //    select new
            //    {
            //        NTitle = newsInfo.nTitle,
            //        TTitle = newsType.tTitle
            //    };

            var list = from newsInfo in dbContext.Set<NewsInfo>()
                       select new NewsTypeViewModel //自定义显示模型来显示部分字段
                {
                    NTitle=newsInfo.nTitle,
                    TTitle=newsInfo.NewsType.tTitle
                };
            
            return View(list);
        }

    }
}

导航属性View部分:

@model IQueryable<t2_EFTest.Models.NewsTypeViewModel>
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @Model.GetType()
        <hr/>
        <table border="1">
            @foreach (var newsinfo in Model)
            {
                <tr>
                    <td>@newsinfo.NTitle</td>
                    <td>@newsinfo.TTitle</td>
                </tr>
            }
        </table>
    </div>
</body>
</html>

自定义的NewsTypeViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace t2_EFTest.Models
{
    public class NewsTypeViewModel
    {
        public string NTitle { get; set; }
        public string TTitle { get; set; }
    }
}

 

单表增删改查操作:

View的Index部分:

@using t2_EFTest.Models
@model IQueryable<t2_EFTest.Models.UserInfo>
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @Html.ActionLink("添加","Add","UserInfoCrud")
        <hr/>
        <table border="1">
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>修改</th>
                <th>删除</th>
            </tr>
            @foreach (UserInfo userInfo in Model)
            {
                <tr>
                    <td>@userInfo.Uid</td>
                    <td>@userInfo.UName</td>
                    <td>
                        @Html.ActionLink("修改","Edit","UserInfoCrud",
                        new RouteValueDictionary(new {id=@userInfo.Uid}),null)
                    </td>
                    <td>
                        @Html.ActionLink("删除",
                        "Remove",
                        "UserInfoCrud",
                        new RouteValueDictionary(new
                        {
                            id=@userInfo.Uid
                        }),null)
                    </td>
                </tr>
            }
        </table>
    </div>
</body>
</html>

Add部分:

@model t2_EFTest.Models.UserInfo
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Add</title>
</head>
<body>
    <div>
        @using (Html.BeginForm("Add", "UserInfoCrud", FormMethod.Post))
        {
            <span>姓名:</span>
            @Html.TextBoxFor(u=>u.UName)
            <br/>
            <input type="submit" value="添加"/>
        }
    </div>
</body>
</html>

Edit

@model t2_EFTest.Models.UserInfo
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Edit</title>
</head>
<body>
    <div>
        @using (Html.BeginForm("Edit", "UserInfoCrud", FormMethod.Post))
        {
            <span>编号:</span>
            @Model.Uid
            @Html.HiddenFor(u=>u.Uid)
            <br/>
            <span>姓名:</span>
            @Html.TextBoxFor(u=>u.UName)
            <br/>
            <input type="submit" value="修改"/>
        }
    </div>
</body>
</html>

 

增删改查Controller部分:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using t2_EFTest.Models;

namespace t2_EFTest.Controllers
{
    public class UserInfoCrudController : Controller
    {
        DbContext dbContext=new MyContext();
        // GET: /UserInfoCrud/

        public ActionResult Index()
        {
            var list = dbContext.Set<UserInfo>();
            return View(list);
        }

        public ActionResult Add()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Add(UserInfo userInfo)
        {
            dbContext.Set<UserInfo>().Add(userInfo);
            int result=dbContext.SaveChanges();//如果内存中的数据发生了变化,并且希望将这个变化映射到数据库,需要执行这个方法
            if (result > 0)
            {
                return Redirect(@Url.Action("Index", "UserInfoCrud"));
            }
            else
            {
                return Redirect(@Url.Action("Add"));
            }
        }

        public ActionResult Edit(int id)
        {
            ViewData.Model = dbContext.Set<UserInfo>()
                .Where(u => u.Uid == id).FirstOrDefault();
            return View();
        }
        [HttpPost]
        public ActionResult Edit(UserInfo userInfo)
        {
            dbContext.Set<UserInfo>().AddOrUpdate(userInfo);
            int result = dbContext.SaveChanges();
            if (result > 0)
            {
                return Redirect(Url.Action("Index"));
            }
            else
            {
                return Redirect(Url.Action("Edit", new RouteValueDictionary(new
                {
                    id = userInfo.Uid
                })));
            }
            
        }

        public ActionResult Remove(int id)
        {
            var userInfo = dbContext.Set<UserInfo>()
                .Where(u => u.Uid == id)
                .FirstOrDefault();
            dbContext.Set<UserInfo>().Remove(userInfo);
            dbContext.SaveChanges();

            return Redirect(Url.Action("Index"));
        }
    }
}

EF生成的实体部分:

namespace t2_EFTest.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class UserInfo
    {
        public int Uid { get; set; }
        public string UName { get; set; }
    }
}

 

 用状态跟踪的方式来修改带导航属性的数据: (上面AddOrUpdate等这种方式实质还是用的状态跟踪方式,只是做了封装而已)

View部分:

@model IQueryable<t2_EFTest.Models.NewsInfo>
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <table border="1">
            <tr>
                <th>编号</th>
                <th>标题</th>
                <th>分类</th>
                <th>修改</th>
            </tr>
            @foreach (var newsInfo in Model)
            {
                <tr>
                    <td>@newsInfo.nid</td>
                    <td>@newsInfo.nTitle</td>
                    <td>@newsInfo.NewsType.tTitle</td>
                    <td>
                        @Html.ActionLink(
                        "修改",
                        "Edit",
                        "NewsInfoCrud",
                        new RouteValueDictionary(new {id=@newsInfo.nid}),
                        null
                        )
                    </td>
                </tr>
            }
        </table>
    </div>
</body>
</html>

 

@model t2_EFTest.Models.NewsInfo
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Edit</title>
</head>
<body>
    <div>
        @using (Html.BeginForm("Edit", "NewsInfoCrud", FormMethod.Post))
        {
            @Model.nid
            @Html.HiddenFor(n=>n.nid)
            <br/>
            @Html.TextBoxFor(n=>n.nTitle)
            <br/>
            <input type="submit" value="修改"/>
        }
    </div>
</body>
</html>

 

Controller部分:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using t2_EFTest.Models;

namespace t2_EFTest.Controllers
{
    public class NewsInfoCrudController : Controller
    {
        // GET: /NewsInfoCrud/
        DbContext dbContext=new MyContext();

        public ActionResult Index()
        {
            ViewData.Model = from newsInfo in dbContext.Set<NewsInfo>() 
                                 select  newsInfo;

            return View();
        }

        public ActionResult Edit(int id)
        {
            ViewData.Model= dbContext.Set<NewsInfo>()
                .Where(n => n.nid == id)
                .FirstOrDefault();

            return View();
        }
[HttpPost]
public ActionResult Edit(NewsInfo newsInfo) { //使用状态方式进行修改 dbContext.Set<NewsInfo>().Attach(newsInfo); //dbContext.Entry(newsInfo).State = EntityState.Modified; //这种方式只适合修改所有字段,包括外键字段,不然会报错 dbContext.Entry(newsInfo).Property("nTitle").IsModified = true; //这种方式适合修改部分列 dbContext.Entry(newsInfo).Property("nTitle").CurrentValue = newsInfo.nTitle; dbContext.SaveChanges(); return Redirect(Url.Action("Index")); } } }

 

 

二、延迟加载 (用的时候才去拿数据)

IQueryable<T>可以使用匿名表达式

 

   延迟加载View部分:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @*@foreach (var userInfo in ViewBag.list)
        {
            @userInfo.Uid
        }*@
        
        <hr/>
       @* @foreach (var userInfo in ViewBag.list)
        {
            @userInfo.Uid
        }*@
        <hr/>
        
       @* @foreach (var userInfo in ViewBag.list2)
        {
            @userInfo.Uid
        }*@
        
        @*@foreach (var newsInfo in ViewBag.list3)
        {
            @newsInfo.NewsType.tid
        }*@
        

    </div>
</body>
</html>

延迟加载controller部分:

using System;
using System.Collections.Generic;
using System.Data.Common.CommandTrees;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using t2_EFTest.Models;

namespace t2_EFTest.Controllers
{
    public class DelayLoadController : Controller
    {
        //
        // GET: /DelayLoad/

        public ActionResult Index()
        {
            DbContext dbContext=new MyContext();

            //延迟加载:如果不使用数据,则只是拼接sql语句,不会将结果集拿到内存中来

            //IQueryable<UserInfo> list = dbContext.Set<UserInfo>()
            //    .OrderByDescending(u => u.Uid)//默认会将lambda表达式封装成Expression对象,而调用IQueryable<T>的方法
            //    .Skip(2)
            //    .Take(3);
            //ViewBag.list = list.ToList(); //结尾增加.ToList或FirstOrDefault()来切换为非延迟加载,直接加载到内存中。

            IEnumerable<UserInfo> list2 = dbContext.Set<UserInfo>()
                .AsEnumerable()
                .OrderByDescending(u => u.Uid)
                .Skip(2)
                .Take(3);
            ViewBag.list2 = list2;

            //导航属性默认也会使用延迟加载
            IQueryable<NewsInfo> list3 = dbContext.Set<NewsInfo>();
            ViewBag.list3 = list3.Include(n=>n.NewsType).ToList();

            return View();
        }

    }
}

 

 

三、EF原理

 

    .edmx文件实质是xml文件,里面包含数据模型定义、概念实体模型和映射关系。

 

 

 

    DbContext把Linq语句转换成Sql语句来执行

 

 

 

DB Fisrt:先设计数据库,然后开发代码。

 

四、Model Fisrt  (先建数据实体模型,然后建模型去生成数据库)

可以进行属性设置:

 

字段设置完成后,转换所有T4模板:

生成了实体类文件:

表之间添加关系:一对一、一对多、多对多

 

根据模型生成数据库:

 

点击完成

执行生成的Sql脚本创建数据库:

 

注意:

如果需要修改或增加字段,可以先修改模型,然后生成T4模板去更新edmx描述文件。

但生成出来的新的Sql脚本不能执行,因为里面是先删除原来的表再创建新的表,之前的表的数据就会丢失,千万不能操作正式库。

但增加字段或修改字段后生成T4模板去更新edmx文件还是要做的,至于数据库表的字段需要手动去数据库去修改字段。

 

 

 

 

五、Code First

在没采用EF的项目中使用EF(中途加入EF)

 

 

六、使用EF与MVC的三层

 

posted @ 2015-10-19 14:30  IT浪潮之巅  阅读(402)  评论(0编辑  收藏  举报
   友情链接: 淘宝优惠券