EntityFramework 的速度还能接受啊

测试准备.Code first entity map.

    public partial class TestDBContext : DbContext
    {
        static TestDBContext()
        {
            Database.SetInitializer<TestDBContext>(null);
        }

        public TestDBContext()
            : base("Name=TestDBContext")
        {
        }

        public DbSet<Category> Categories { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new CategoryMap());
        }
    }

    public class CategoryMap : EntityTypeConfiguration<Category>
    {
        public CategoryMap()
        {
            // Primary Key
            this.HasKey(t => t.Id);

            // Properties
            this.Property(t => t.Name)
                .IsRequired()
                .HasMaxLength(50);

            this.Property(t => t.Description)
                .IsRequired()
                .HasMaxLength(50);

            // Table & Column Mappings
            this.ToTable("Category");
            this.Property(t => t.Id).HasColumnName("Id");
            this.Property(t => t.Name).HasColumnName("Name");
            this.Property(t => t.Description).HasColumnName("Description");
            this.Property(t => t.Date).HasColumnName("Date");
        }
    }

    public partial class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public System.DateTime Date { get; set; }
    }
View Code

EF6, 

PM> Install-Package EntityFramework -Pre

测试用例:

    class Program
    {
        static void Main(string[] args)
        {
            using (TestDBContext context = new TestDBContext())
            {
                for (int i = 0; i < 5; i++)
                {
                    var length = (int)Math.Pow(10, i);
                    Console.WriteLine();
                    Console.WriteLine("Test Insert {0} datas", length);
                    NewMethod(context, length);
                }

            }
            Console.WriteLine("Complete");
            Console.ReadKey();
        }

        private static void NewMethod(TestDBContext context, int length)
        {
            Console.WriteLine("------------------------------------------");
            Console.WriteLine("Command\t|\tTime\t|\tDescription");
            Console.WriteLine("------------------------------------------");
            Stopwatch watch = Stopwatch.StartNew();
            var count = context.Categories.Count();
            Log(watch, "Count", "First count", count);
            count = context.Categories.Count(c => c.Id % 2 == 0);
            Log(watch, "Count", "Count name end with 1", count);
            context.Categories.RemoveRange(context.Categories);
            context.SaveChanges();
            count = context.Categories.Count();
            Log(watch, "Delete", "Delete all datas", count);
            var list = GenerateDatas(length);
            Log(watch, "Gen", "Generate " + length + " Datas fro added", count);
            context.Categories.AddRange(list);
            context.SaveChanges();
            count = context.Categories.Count();
            Log(watch, "Add", "Add " + length + " datas", count);
            foreach (var item in context.Categories.Where(c => c.Name.EndsWith("1")))
            {
                item.Name = "Update";
            }
            context.SaveChanges();
            count = context.Categories.Count();
            Log(watch, "Update", "Update datas", count);
        }

        private static void Log(Stopwatch watch, string cmd, string desc, int count)
        {
            watch.Stop();
            Console.WriteLine("{0}\t|\t{1}ms\t|\t{2},DB has {3} datas", cmd, watch.ElapsedMilliseconds, desc, count);
            watch.Restart();
        }

        private static ConcurrentBag<Category> GenerateDatas(int p)
        {
            ConcurrentBag<Category> bag = new ConcurrentBag<Category>();
            Parallel.For(0, p, c =>
            {
                var data = new Category()
                {
                    Name = "New Name" + c,
                    Date = DateTime.Now,
                    Description = "Test for insert"
                };
                bag.Add(data);
            });
            return bag;
        }
    }
View Code

结果:

 1 Test Insert 1 datas
 2 ------------------------------------------
 3 Command |       Time    |       Description
 4 ------------------------------------------
 5 Count   |       5050ms  |       First count,DB has 10000 datas
 6 Count   |       142ms   |       Count name end with 1,DB has 5000 datas
 7 Delete  |       3869ms  |       Delete all datas,DB has 0 datas
 8 Gen     |       2ms     |       Generate 1 Datas fro added,DB has 0 datas
 9 Add     |       172ms   |       Add 1 datas,DB has 1 datas
10 Update  |       40ms    |       Update datas,DB has 1 datas
11 
12 Test Insert 10 datas
13 ------------------------------------------
14 Command |       Time    |       Description
15 ------------------------------------------
16 Count   |       2ms     |       First count,DB has 1 datas
17 Count   |       4ms     |       Count name end with 1,DB has 1 datas
18 Delete  |       6ms     |       Delete all datas,DB has 0 datas
19 Gen     |       0ms     |       Generate 10 Datas fro added,DB has 0 datas
20 Add     |       7ms     |       Add 10 datas,DB has 10 datas
21 Update  |       18ms    |       Update datas,DB has 10 datas
22 
23 Test Insert 100 datas
24 ------------------------------------------
25 Command |       Time    |       Description
26 ------------------------------------------
27 Count   |       1ms     |       First count,DB has 10 datas
28 Count   |       5ms     |       Count name end with 1,DB has 5 datas
29 Delete  |       32ms    |       Delete all datas,DB has 0 datas
30 Gen     |       0ms     |       Generate 100 Datas fro added,DB has 0 datas
31 Add     |       78ms    |       Add 100 datas,DB has 100 datas
32 Update  |       14ms    |       Update datas,DB has 100 datas
33 
34 Test Insert 1000 datas
35 ------------------------------------------
36 Command |       Time    |       Description
37 ------------------------------------------
38 Count   |       1ms     |       First count,DB has 100 datas
39 Count   |       6ms     |       Count name end with 1,DB has 50 datas
40 Delete  |       35ms    |       Delete all datas,DB has 0 datas
41 Gen     |       0ms     |       Generate 1000 Datas fro added,DB has 0 datas
42 Add     |       397ms   |       Add 1000 datas,DB has 1000 datas
43 Update  |       42ms    |       Update datas,DB has 1000 datas
44 
45 Test Insert 10000 datas
46 ------------------------------------------
47 Command |       Time    |       Description
48 ------------------------------------------
49 Count   |       3ms     |       First count,DB has 1000 datas
50 Count   |       4ms     |       Count name end with 1,DB has 500 datas
51 Delete  |       253ms   |       Delete all datas,DB has 0 datas
52 Gen     |       6ms     |       Generate 10000 Datas fro added,DB has 0 datas
53 Add     |       5203ms  |       Add 10000 datas,DB has 10000 datas
54 Update  |       470ms   |       Update datas,DB has 10000 datas
55 Complete
View Code

这个结果还能接受吧.

从Profiler可以看到.

Get Count 产生一条Script

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[Category] AS [Extent1]
)  AS [GroupBy1]
--
SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM [dbo].[Category] AS [Extent1]
    WHERE (0 = ([Extent1].[Id] % 2)) AND ([Extent1].[Id] % 2 IS NOT NULL)
)  AS [GroupBy1]
View Code

Delete产生N条Script

exec sp_executesql N'delete [dbo].[Category]
where ([Id] = @0)',N'@0 int',@0=xxxxx
View Code

Insert也是产生N条Script

exec sp_executesql N'insert [dbo].[Category]([Name], [Description], [Date])
values (@0, @1, @2)
select [Id]
from [dbo].[Category]
where @@ROWCOUNT > 0 and [Id] = scope_identity()',N'@0 nvarchar(50),@1 nvarchar(50),@2 datetime2(7)',@0=N'New Name2712',@1=N'Test for insert',@2='2013-06-07 14:10:47.3691406'
View Code

Update又是N条Script

exec sp_executesql N'update [dbo].[Category]
set [Name] = @0
where ([Id] = @1)
',N'@0 nvarchar(50),@1 int',@0=N'Update',@1=149258
View Code

从执行的Script来看,能做可以把那些N条的减少为一条或少于N条.

Delete 是批量删除,可以合为一条;

Insert,即使是手工写也是写union all那种形式,这个就先不改了.

Update属于条件批量更新,可以合为一条.

批量操作,EF有个第三方的扩展库还行.

虽然EF现在出了6.0 beta版本,但这个扩展还不完全支持EF6.0

所以下个测试用EF5.0

Install-Package EntityFramework -Version 5.0.0

Install-Package EntityFramework.Extended

数据和实体类不变,把测试用例修改些.

引用命名空间

using EntityFramework.Extensions;
作例代码
static void Main(string[] args)
        {
            using (TestDBContext context = new TestDBContext())
            {
                for (int i = 0; i < 5; i++)
                {
                    var length = (int)Math.Pow(10, i);
                    Console.WriteLine();
                    Console.WriteLine("Test Insert {0} datas", length);
                    NewMethod(context, length);
                }

            }
            Console.WriteLine("Complete");
            Console.ReadKey();
        }

        private static void NewMethod(TestDBContext context, int length)
        {
            Console.WriteLine("------------------------------------------");
            Console.WriteLine("Command\t|\tTime\t|\tDescription");
            Console.WriteLine("------------------------------------------");
            Stopwatch watch = Stopwatch.StartNew();
            var count = context.Categories.Count();
            Log(watch, "Count", "First count", count);
            count = context.Categories.Count(c => c.Id % 2 == 0);
            Log(watch, "Count", "Count name end with 1", count);
            context.Categories.Delete();
            context.SaveChanges();
            count = context.Categories.Count();
            Log(watch, "Delete", "Delete all datas", count);
            var list = GenerateDatas(length);
            Log(watch, "Gen", "Generate " + length + " Datas fro added", count);
            var v = ((IObjectContextAdapter)context).ObjectContext;
            foreach (var item in list)
            {
                v.AddObject("Categories", item);
            }
            context.SaveChanges();
            count = context.Categories.Count();
            Log(watch, "Add", "Add " + length + " datas", count);
            context.Categories.Update(c => c.Name.EndsWith("1"), c => new Category() { Name = "Update" });
            context.SaveChanges();
            count = context.Categories.Count();
            Log(watch, "Update", "Update datas", count);
        }

        private static void Log(Stopwatch watch, string cmd, string desc, int count)
        {
            watch.Stop();
            Console.WriteLine("{0}\t|\t{1}ms\t|\t{2},DB has {3} datas", cmd, watch.ElapsedMilliseconds, desc, count);
            watch.Restart();
        }

        private static ConcurrentBag<Category> GenerateDatas(int p)
        {
            ConcurrentBag<Category> bag = new ConcurrentBag<Category>();
            Parallel.For(0, p, c =>
            {
                var data = new Category()
                {
                    Name = "New Name" + c,
                    Date = DateTime.Now,
                    Description = "Test for insert"
                };
                bag.Add(data);
            });
            return bag;
        }
View Code

其中用了

 context.Categories.Delete();
批量删除.
var v = ((IObjectContextAdapter)context).ObjectContext;
            foreach (var item in list)
            {
                v.AddObject("Categories", item);
            }修改Add操作方式
 context.Categories.Update(c => c.Name.EndsWith("1"), c => new Category() { Name = "Update" });
批量更新.

结果
 1 Test Insert 1 datas
 2 ------------------------------------------
 3 Command |       Time    |       Description
 4 ------------------------------------------
 5 Count   |       1026ms  |       First count,DB has 10000 datas
 6 Count   |       6ms     |       Count name end with 1,DB has 5000 datas
 7 Delete  |       558ms   |       Delete all datas,DB has 0 datas
 8 Gen     |       2ms     |       Generate 1 Datas fro added,DB has 0 datas
 9 Add     |       342ms   |       Add 1 datas,DB has 1 datas
10 Update  |       53ms    |       Update datas,DB has 1 datas
11 
12 Test Insert 10 datas
13 ------------------------------------------
14 Command |       Time    |       Description
15 ------------------------------------------
16 Count   |       2ms     |       First count,DB has 1 datas
17 Count   |       1ms     |       Count name end with 1,DB has 1 datas
18 Delete  |       13ms    |       Delete all datas,DB has 0 datas
19 Gen     |       0ms     |       Generate 10 Datas fro added,DB has 0 datas
20 Add     |       12ms    |       Add 10 datas,DB has 10 datas
21 Update  |       9ms     |       Update datas,DB has 10 datas
22 
23 Test Insert 100 datas
24 ------------------------------------------
25 Command |       Time    |       Description
26 ------------------------------------------
27 Count   |       1ms     |       First count,DB has 10 datas
28 Count   |       2ms     |       Count name end with 1,DB has 5 datas
29 Delete  |       7ms     |       Delete all datas,DB has 0 datas
30 Gen     |       0ms     |       Generate 100 Datas fro added,DB has 0 datas
31 Add     |       53ms    |       Add 100 datas,DB has 100 datas
32 Update  |       8ms     |       Update datas,DB has 100 datas
33 
34 Test Insert 1000 datas
35 ------------------------------------------
36 Command |       Time    |       Description
37 ------------------------------------------
38 Count   |       1ms     |       First count,DB has 100 datas
39 Count   |       1ms     |       Count name end with 1,DB has 50 datas
40 Delete  |       6ms     |       Delete all datas,DB has 0 datas
41 Gen     |       0ms     |       Generate 1000 Datas fro added,DB has 0 datas
42 Add     |       418ms   |       Add 1000 datas,DB has 1000 datas
43 Update  |       29ms    |       Update datas,DB has 1000 datas
44 
45 Test Insert 10000 datas
46 ------------------------------------------
47 Command |       Time    |       Description
48 ------------------------------------------
49 Count   |       1ms     |       First count,DB has 1000 datas
50 Count   |       1ms     |       Count name end with 1,DB has 500 datas
51 Delete  |       21ms    |       Delete all datas,DB has 0 datas
52 Gen     |       3ms     |       Generate 10000 Datas fro added,DB has 0 datas
53 Add     |       4365ms  |       Add 10000 datas,DB has 10000 datas
54 Update  |       128ms   |       Update datas,DB has 10000 datas
55 Complete
View Code


从Profiler可以看到.

DELETE变成一条Script了

1 DELETE [dbo].[Category]
2 FROM [dbo].[Category] AS j0 INNER JOIN (
3 SELECT 
4 [Extent1].[Id] AS [Id]
5 FROM [dbo].[Category] AS [Extent1]
6 ) AS j1 ON (j0.[Id] = j1.[Id])
View Code

UPDATE也变为一条了

1 exec sp_executesql N'UPDATE [dbo].[Category] SET 
2 [Name] = @p__update__0 
3 FROM [dbo].[Category] AS j0 INNER JOIN (
4 SELECT 
5 [Extent1].[Id] AS [Id]
6 FROM [dbo].[Category] AS [Extent1]
7 WHERE [Extent1].[Name] LIKE N''%1''
8 ) AS j1 ON (j0.[Id] = j1.[Id])',N'@p__update__0 nvarchar(6)',@p__update__0=N'Update'
View Code

EF5和EF6都差不多,都能接受.

你可能感兴趣的:(framework)