天天看点

Entity Framework 4.1: Basics (1)

  As its name suggest, with code-first, you start with the code.  You can

create the corresponding database directly from the code, but you could

also be working from an existing DB.  The advantage of code-first is

that your entity-classes don’t have any EF artefacts on them:  they

don’t derive from a specific class and they do not have funky attributes

on them.  Well…  for the attributes, as we’ll see, that’s optional!

  Let’s start with a simple entity model:  Order and OrderDetail.  We

start by modelling it as classes:

public class Order

{

    public int

OrderID { get; set; }

    public string OrderTitle { get; set; }

    public string CustomerName { get; set; }

public DateTime TransactionDate { get; set; }

    public List<OrderDetail> OrderDetails { get; set; }

}

public class OrderDetail

OrderDetailID { get; set; }

    public int OrderID { get; set; }

    public decimal Cost { get; set; }

    public

string ItemName { get; set; }

    public Order Order { get; set; }

  

  Note the following about those classes:

  • They do not derive from any EF classes
  • They do not use EF attributes
  • An Order contains a list of OrderDetail and

    an OrderDetail contains a reference to its Order

  • Each property is either
    • A simple CLR Type (e.g. string, int, etc.)
    • An entity-type (e.g. Order)
    • A list of entity type (e.g. List<OrderDetail>)

In order to map those class into a DB, we need a container, a

database-context:

public class MyDomainContext : DbContext

public DbSet<Order> Orders { get; set; }

DbSet<OrderDetail> OrderDetails { get; set; }

    static MyDomainContext()

    {

Database.SetInitializer<MyDomainContext>(new

DropCreateDatabaseIfModelChanges<MyDomainContext>());

}

This class is EF-aware.  It doesn’t have to sit in the same assembly

than your model classes though.

At least a context must satisfy the following:

  • It derives from System.Data.Entity.DbContext
  • It has a property for each entity set we want to expose
  • Each property is of type System.Data.Entity.DbSet<T>

    where T is the type of the entity

  • Each property is read / write (get / set)

With that in place在这里, the DbContext base class uses reflection

to pick-up the entity-sets and a bunch of convention to infer the

underlying database model it should map to.

The conventions take decisions such as for the entity of type

Order, the property OrderID must be its primary key.  Other

convention will infer the column-name (by default the property name),

the column type (e.g. a string maps to nvarchar(128) and should be

nvarchar(MAX) in the

final

version

), if a column is nullable (by default, all column but

primary and foreign keys are nullable), etc.  .  We’ll see that there

are ways to override those conventions.

We’ve added a static constructor here.  The instruction in the static

constructor sets a standard for the entire app-domain:  when a database

context is initialized, check if the schema in the database is conform

to the model and if not drop the DB and recreate it.  The way this is

done is that EF creates a table dbo.EdmMetadata and persist a

hash of the model schema in it.

If the database doesn’t exist, EF will create it.  Which database? 

By default, it creates a DB with the name of your context on the local

machine.  You can override that in many ways.  The simplest is to add a

connection string in your configuration file with the name of the

context (in my case, "MyDomainContext").  Another way is to

implement a constructor and call the non-default base-class constructor

in it.

In the next blob entry, I’ll show how to override the conventions.

继续阅读