网站/小程序/APP个性化定制开发,二开,改版等服务,加扣:8582-36016

    这篇文章介绍了Entity Framework使用DBContext实现增删改查的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    有一段时间没有更新博客了,赶上今天外面下雨,而且没人约球,打算把最近对Entity Framework DBContext使用的心得梳理一下,早些时候在网上简单查过,对于最新版本的EF并没有类似的知识梳理类文章,希望对大家有所帮助。

    1. 不要Code first, 也不要DB first

    我为什么讨厌Code first和DB first呢?首先Code first是先写代码,数据库完全由代码生成,开发阶段尚可,一旦到了产品发布阶段,如果需要添加字段,我们总不能用 visual studio去生产环境上去更新数据库吧,听起来就很可怕。而且另外的一个问题自动是生成的数据库脚本也不可控,还不如自己提前设计好。DB first也好不了哪去,反向转过来的代码包含很多没有用的文件,而且数据库的更新还要重新走Model生成过程,简直无法理解为什么会有这样的设计。说了这么多,怎么解决呢?

    数据库和领域模型分开设计,按照对应关系映射字段,使用自定义链接字串,既不使用领域模型生成数据库,也不用数据库生成领域模型,示例代码如下,SQL Code 以 Destinations和TTable表为例:

    CREATE TABLE [DBO].[Destinations]
    (
        [DestinationId] [int] PRIMARY KEY NOT NULL,
        [Name] [nvarchar](max) NULL,
        [Country] [nvarchar](max) NULL,
        [Description] [nvarchar](max) NULL,
        [Photo] [varbinary](max) NULL
    CREATE TABLE [TTT].[TTable]
     (
      [Id] [int] PRIMARY KEY NOT NULL,
      [Name] [nvarchar](max) NULL
     )

    Model Class:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
     namespace Model
    {
        public class Destination
        {
            public int DestinationId { get; set; }
            public string Name { get; set; }
            public string Country { get; set; }
            public string Description { get; set; }
            public byte[] Photo { get; set; }
            public List<Lodging> Lodgings { get; set; }
        }
         public class Lodging
        {
            public int LodgingId { get; set; }
            public string Name { get; set; }
            public string Owner { get; set; }
            public bool IsResort { get; set; }
            public Destination Destination { get; set; }
        }
         public class TTable
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    }

    Connect String:

    <connectionStrings>
        <add name="BAContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;
        Initial Catalog=DataAccess.BreakAwayContext;Integrated Security=SSPI;" 
        providerName="System.Data.SqlClient" />
      </connectionStrings>

    DB Context:

    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration;
    using Model;
     namespace DataAccess
    {
        public class TTableConfiguration : EntityTypeConfiguration<TTable>
        {
            public TTableConfiguration()
            {
                this.ToTable("TTable", "TTT");
            }
        }
         public class BreakAwayContext : DbContext
        {
             protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Configurations.Add(new TTableConfiguration());
            }
             public BreakAwayContext(string connString) : base(connString)
            {
            }
            public DbSet<Destination> Destinations { get; set; }
            public DbSet<Lodging> Lodgings { get; set; }
            public DbSet<TTable> TTables { get; set; }
        }
    }

    2. 如果数据库的表的字段和领域模型的字段不对应,如何处理呢?比如本文的TTable表是在TTT  Schema下面的, 而其他表示设计在DBO下面,最方便的方式是使用fluent API, 具体代码如请参见 TTableConfiguration Class和 OnModelCreating()方法,可配置的粒度非常细,比如可以配置领域模型和数据库的哪个Schema的哪张表的哪一列对应,本文是将TTable 类的数据库表配置为了TTT  Schema下的TTable表,

    public class TTableConfiguration : EntityTypeConfiguration<TTable>
    {
        public TTableConfiguration()
        {
            this.ToTable("TTable", "TTT");
        }
    }

    3. 增删该查自带事物支持,具体代码如下,

    public static int Insert()
    {
        var destination = new Destination
        {
            Country = "Chs",
            Description = "Chs is the language package",
            Name = "xsss"
        };
        using (var context = new BreakAwayContext(ConfigurationManager.
        ConnectionStrings["BAContext"].ConnectionString))
        {
            var rt = context.Destinations.Add(destination);
            context.SaveChanges();
            return rt.DestinationId;
        }
    }
     public static void Update(Destination destIn)
    {
        using (var context = new BreakAwayContext(ConfigurationManager.
        ConnectionStrings["BAContext"].ConnectionString))
        {
            var dest = context.Destinations.Where(a => a.DestinationId == 
            destIn.DestinationId).Single();
            dest.Name = destIn.Name;
            context.SaveChanges();
        }
    }
     public static void Delete(int destId)
    {
        using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings
        ["BAContext"].ConnectionString))
        {
            var destination = new Destination() { DestinationId = destId };
            context.Destinations.Attach(destination);
            context.Destinations.Remove(destination);
             context.SaveChanges();
        }
    }
      public static Destination Query(int destId)
    {
        using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings
        ["BAContext"].ConnectionString))
        {
            IQueryable<Destination> dest = context.Destinations.Where(a => a.DestinationId 
            == destId);
             return dest.Single();
        }
    }

    4. 如果需要多个操作同时成功或者失败,需要手动开启事务,具体代码如下,

    public static void TransactionOps()
    {
        using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings
        ["BAContext"].ConnectionString))
        {
            using (var dbContextTransaction = context.Database.BeginTransaction())
            {
                try
                {
                    var destination = new Destination
                    {
                        Country = "Chs",
                        Description = "Chs is the language package",
                        Name = "xs2s"
                    };
                     var destId = context.Destinations.Add(destination);
                     context.SaveChanges();
                     context.Destinations.Attach(destId);
                    context.Destinations.Remove(destId);
                     context.SaveChanges();
                     dbContextTransaction.Commit();
                }
                catch (System.Exception ex)
                {
                    dbContextTransaction.Rollback();
                    System.Console.WriteLine(ex.ToString());
                }
            }
        }
    }

    5. 分页查询是网站设计的常用功能,一个简单的真分页查询方法如下如下所示,

    public static List<Destination> QueryPaging<TKey>(int pageIndex, int pageSize, Expression<Func
    <Destination, bool>> whereLambda, Expression<Func<Destination, TKey>> orderBy)
    {
        using (var context = new BreakAwayContext(ConfigurationManager.ConnectionStrings
        ["BAContext"].ConnectionString))
        {
            return context.Destinations.Where(whereLambda).OrderBy(orderBy).Skip((pageIndex - 1)
             * pageSize).Take(pageSize).ToList();
        }
    }

    总结

    本文对最新版本的Entity Framework进行增删改查操作给出了详尽的解释,并且给出了数据库和领域模型代码分开设计的完整解决方案,同时介绍了手动数据库表和领域模型映射,数据库事务实现,分页查询等常用功能,希望对大家有所帮助。


    评论 0

    暂无评论
    0
    0
    0
    立即
    投稿
    发表
    评论
    返回
    顶部