具有实体框架的单身人士:查询会多次运行吗?

时间:2010-09-02 05:07:51

标签: c# entity-framework-4

使用像......这样的模型。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.ComponentModel.DataAnnotations;

namespace Singleton
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = new ModelBuilder();

            builder.Configurations.Add(new TemplateConfiguration());
            builder.Configurations.Add(new UserConfiguration());
            builder.Configurations.Add(new UnitConfiguration());
            builder.Configurations.Add(new AttributeConfiguration());

            var model = builder.CreateModel();

            using (var context = new SampleDataContext(model))
            {
                bool updating = true;
                if (updating)
                {
                    var units = new List<Unit>
                {
                    new Unit{ Name = "Unit1" },
                    new Unit{ Name = "Unit2" }
                };

                    units.ForEach(x => { context.Units.Add(x); });
                    context.SaveChanges();

                    var templates = new List<Template>
                {
                    new Template{
                        Name = "Default",
                        Attributes = new List<Attribute>
                        {
                            new Attribute
                            {
                                Unit = context.Units.Single( i => i.Name == "Unit1" )
                            }
                        }
                    }
                };

                    templates.ForEach(x =>
                    {
                        context.Templates.Add(x);
                    });
                    context.SaveChanges();
                    var users = new List<User>
                {
                    new User
                    {
                        Name = "Stacey"
                    },
                    new User
                    {
                        Name = "Daniel"
                    },
                    new User
                    {
                        Name = "Derek"
                    }
                };

                    users.ForEach(x => { context.Users.Add(x); });
                    context.SaveChanges();

                    updating = !updating; // stop updating
                }

                if (!updating)
                {
                    Single.Instance = context.Templates.Single(i => i.Name == "Default");
                }

                foreach (User user in context.Users)
                {
                    Console.WriteLine(user.Template.Name); // does template requery?
                }
            }
        }
    }
    public class Template
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual ICollection<Attribute> Attributes { get; set; }
    }

    public class TemplateConfiguration : EntityConfiguration<Template>
    {
        public TemplateConfiguration()
        {
            HasKey(k => k.Id);
            Property(k => k.Id).IsIdentity();
            Property(k => k.Name);

            //// map the collection entity
            HasMany(k => k.Attributes).WithRequired()
                .Map("template.attributes",
                    (template, attribute) => new
                    {
                        Template = template.Id,
                        Attribute = attribute.Id
                    });

            MapSingleType(c => new
            {
                c.Id,
                c.Name
            }).ToTable("templates");
        }
    }

    public class User
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }

        [StoreGenerated(StoreGeneratedPattern.None)]
        public Template Template { get { return Single.Instance; } }
    }

    public class UserConfiguration : EntityConfiguration<User>
    {
        public UserConfiguration()
        {
            HasKey(k => k.Id);
            Property(k => k.Id).IsIdentity();
            Property(k => k.Name);

            MapSingleType(c => new
            {
                c.Id,
                c.Name
            }).ToTable("users");
        }
    }

    public class Unit
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
    }

    public class UnitConfiguration : EntityConfiguration<Unit>
    {
        public UnitConfiguration()
        {
            HasKey(k => k.Id);
            Property(k => k.Id).IsIdentity();
            Property(k => k.Name);

            MapSingleType(c => new
            {
                c.Id,
                c.Name
            }).ToTable("units");
        }
    }

    public class Attribute
    {
        public virtual int Id { get; set; }
        public Unit Unit { get; set; }
    }

    public class AttributeConfiguration : EntityConfiguration<Attribute>
    {
        public AttributeConfiguration()
        {
            HasKey(k => k.Id);
            Property(k => k.Id).IsIdentity();
            // Initialize the Statistic
            HasRequired(k => k.Unit);

            // map the data type to the context so that it can be queried.
            MapHierarchy(c => new
            {
                c.Id,
                Unit = c.Unit.Id
            }).ToTable("attributes");
        }
    }
    public class Single
    {
        public static Template Instance;
    }

    public class SampleDataContext : DbContext
    {
        public SampleDataContext(DbModel model)
            : base(model)
        {
            this.ObjectContext.ContextOptions.LazyLoadingEnabled = true;
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }

        public DbSet<Template> Templates { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<Unit> Units { get; set; }
        public DbSet<Attribute> Attributes { get; set; }
    }
}

如果我将Singleton.Instance分配给DataContext中的查询,然后将Singleton.Instance分配给我的代码中的其他对象,SQL会运行一次,还是每次访问它?任何人都可以帮助我看看这种模式是否会节省一些SQL吗?

2 个答案:

答案 0 :(得分:2)

每次访问时都会运行SQL。 您正在寻找的是某种缓存策略。

查看以下主题。我认为它会对你有所帮助:How to make Entity Framework cache some objects

答案 1 :(得分:2)

从context.SomeQuery,你几乎肯定只是返回某种可查询对象或其他可迭代对象(我不确定你的例子反映了你的EF解决方案是如何实际构建的,我认为有些元素因为简洁)。因此,每次访问此单例时,您只需再次迭代它(运行查询)。

我建议您使用围绕4.0缓存的简单memoization,尝试this