这个是 ADO.NET Blog 上的一个系列,我用来参考快速学习 Entity Framework 框架。按照作者推荐先学习 “EF 4.1 Code First Walkthrough” (摘要)和 “EF 4.1 Model & Database First Walkthrough” (摘要)之后再开始这一系列学习。
Series Contents
Part 1: Introduction and Model
- Introduces the topics that will be covered in the series
- Presents a Code First model that will be used in the subsequent parts
Part 2: Connections and Models
- Covers using DbContext constructors to configure the database connection and set the context to work in Code First, Model First, or Database First mode
- Shows different ways that the DbSet properties on the context can be defined
- Shows how an entity can be retrieved using its primary key value.
Part 4: Add/Attach and Entity States
- Shows different ways to add a new entity to the context or attach an existing entity to the context
- Covers the different entity states and shows how to change the state of an entity
Part 5: Working with Property Values
- Shows how to get and set the current and original values of individual properties
- Covers different ways of working with all the property values of an entity
- Shows how to get and set the modified state of a property
Part 6: Loading Related Entities
- Covers the loading related entities eagerly, lazily, and explicitly
- Shows how to work locally with entities that are already being tracked by the context
- Provides some general information on the facilities provided by DbContext for data binding
- Presents some useful tips for working with dynamically generated entity proxies
Part 9: Optimistic Concurrency Patterns
- Shows some common patterns for handling optimistic concurrency exceptions
- Shows how to send raw queries and commands to the database
Part 11: Load and AsNoTracking
- Covers the Load and AsNoTracking LINQ extension methods for loading entities into the context and querying entities with having them be tracked by the context
Part 12: Automatically Detecting Changes
- Describes when and how DbContext automatically detects changes in entities provides some pointers for when to switch this off
Model Description
The model below contains four entity types: Princess, Unicorn, Castle, and LadyInWaiting. A princess can have many unicorns and each unicorn is owned by exactly one princess. A princess has exactly one lady-in-waiting in each castle.
A castle has a location represented by the complex type Location, which in turn has a nested complex type ImaginaryWorld
Model Code
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Data.Metadata.Edm; using System.Data.Objects; using System.Linq; namespace Magic.Unicorn { public class Princess : IPerson { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Unicorn> Unicorns { get; set; } public virtual ICollection<LadyInWaiting> LadiesInWaiting { get; set; } } public class Unicorn { public int Id { get; set; } public string Name { get; set; } [Timestamp] public byte[] Version { get; set; } public int PrincessId { get; set; } // FK for Princess reference public virtual Princess Princess { get; set; } } public class Castle { [Key] public string Name { get; set; } public Location Location { get; set; } public virtual ICollection<LadyInWaiting> LadiesInWaiting { get; set; } } [ComplexType] public class Location { public string City { get; set; } public string Kingdom { get; set; } public ImaginaryWorld ImaginaryWorld { get; set; } } [ComplexType] public class ImaginaryWorld { public string Name { get; set; } public string Creator { get; set; } } public class LadyInWaiting : IPerson { [Key, Column(Order = 0)] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int PrincessId { get; set; } // FK for Princess reference [Key, Column(Order = 1)] public string CastleName { get; set; } // FK for Castle reference public string FirstName { get; set; } public string Title { get; set; } [NotMapped] public string Name { get { return String.Format("{0} {1}", Title, FirstName); } } public virtual Castle Castle { get; set; } public virtual Princess Princess { get; set; } } public interface IPerson { string Name { get; } } public class UnicornsContext : DbContext { public DbSet<Unicorn> Unicorns { get; set; } public DbSet<Princess> Princesses { get; set; } public DbSet<LadyInWaiting> LadiesInWaiting { get; set; } public DbSet<Castle> Castles { get; set; } } public class UnicornsContextInitializer : DropCreateDatabaseAlways<UnicornsContext> { protected override void Seed(UnicornsContext context) { var cinderella = new Princess { Name = "Cinderella" }; var sleepingBeauty = new Princess { Name = "Sleeping Beauty" }; var snowWhite = new Princess { Name = "Snow White" }; new List<Unicorn> { new Unicorn { Name = "Binky" , Princess = cinderella }, new Unicorn { Name = "Silly" , Princess = cinderella }, new Unicorn { Name = "Beepy" , Princess = sleepingBeauty }, new Unicorn { Name = "Creepy" , Princess = snowWhite } }.ForEach(u => context.Unicorns.Add(u)); var efCastle = new Castle { Name = "The EF Castle", Location = new Location { City = "Redmond", Kingdom = "Rainier", ImaginaryWorld = new ImaginaryWorld { Name = "Magic Unicorn World", Creator = "ADO.NET" } }, }; new List<LadyInWaiting> { new LadyInWaiting { Princess = cinderella, Castle = efCastle, FirstName = "Lettice", Title = "Countess" }, new LadyInWaiting { Princess = sleepingBeauty, Castle = efCastle, FirstName = "Ulrika", Title = "Lady" }, new LadyInWaiting { Princess = snowWhite, Castle = efCastle, FirstName = "Yolande", Title = "Duchess" } }.ForEach(l => context.LadiesInWaiting.Add(l)); } } public class Program { public static void Main(string[] args) { Database.SetInitializer(new UnicornsContextInitializer()); // Many of the code fragments can be run by inserting them here } } }