Blog

Filter posts by Category Or Tag of the Blog section!

Getting started with Entity Framework

Thursday, 06 September 2012

 What is Entity Framework !?

MSDN answers to this question: "Entity Framework is an Object Relational Mapper (ORM). It basically generates business objects and entities according to the database tables provides the ability to do CRUD operations, relations and etc."

And also about Wikipedia's definition: "The Entity Framework is a set of technologies in ADO.NET that support the development of data-oriented software applications. Architects and developers of data-oriented applications have struggled with the need to achieve two very different objectives. They must model the entities, relationships, and logic of the business problems they are solving, and they must also work with the data engines used to store and retrieve the data. The data may span multiple storage systems, each with its own protocols; even applications that work with a single storage system must balance the requirements of the storage system against the requirements of writing efficient and maintainable application code. The Entity Framework enables developers to work with data in the form of domain-specific objects and properties, such as customers and customer addresses, without having to concern themselves with the underlying database tables and columns where this data is stored. With the Entity Framework, developers can work at a higher level of abstraction when they deal with data and can create and maintain data-oriented applications with less code than in traditional applications. Because the Entity Framework is a component of the .NET Framework, Entity Framework applications can run on any computer on which the .NET Framework starting with version 3.5 SP1 is installed."

 

Forget about definitions and just Make your hands dirty to learn!

I just Use the code first feature of entity framework, it means creating our model and then creating database based on Model, in other words, you can use C# or VB class to generate the database, and also you can map your model to an existing database (if your database has been designed earlier).

there are lots of reason why I'm interested in to use Code first .in entity framework you can customize persistence easily, it is better when you are going to write Unit test, and more about the persistence of Ignorance (I'm not going to talk about this one in the current article)

Note: You can use code first feature via at least version 4.1 or later.

I'm using Asp.net MVC in this article, Create a class with this definition :

 

    public class Account
     {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Balance { get; set; }
      }

 

Now create your context class:

 

 public class ContextClass : DbContext
    {
       public ContextClass(string connectionString) :base(connectionString)
        {
        }
       public DbSet<Account> Accounts { get; set; }
    }

 

And in Web.config  :

 

<connectionStrings>
    <add name="ContextClass" connectionString="Data Source=EHSAN-PC;Initial Catalog=BlogArticle;Integrated Security=SSPI" providerName="System.Data.SqlClient" />
 </connectionStrings>

 

Now create a simple controller to calling the context class to finalize the creating the database in your management studio

 

    public class EntityFrameworkController : Controller
    {
        private ContextClass _contextClass;

        public EntityFrameworkController()
        {
            _contextClass = new ContextClass();
        }
      
        public ActionResult Index()
        {
            Account account= _contextClass.Accounts.First();
            return View(account);
        }     
    }

 

Just run the project and request this Index action In Url, you can also create some fake data by hard coding in the action. If you go to SQL management studio, you have created the blog article database successfully! So, database tables  built by DbContext based on model properties by running the project, now if we make any change in our domain model, database tables and our model won't be compatible, to solve this, change  your ContextClass like this :

 

 public class ContextClass : DbContext
    {
        public ContextClass()
        {
            if (this.Database.Exists() && !this.Database.CompatibleWithModel(false))
                this.Database.Delete();
            if (!this.Database.Exists()) this.Database.Create();
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }
        public DbSet<Account> Accounts { get; set; }
    }

 

Initializing the database :

Entity framework provides to initialize the database with fake data, to do this add a new class to project with this definition:

 

    public class InitializerClass :DropCreateDatabaseIfModelChanges<ContextClass>
    {
        protected override void Seed(ContextClass context)
        {
            new List<Account>
                {
                    new Account {Id = 1, Balance = 34523, Name = "Mark"}
                };
            base.Seed(context);
        }
    }

 

And also you have to add this in global.asax

 

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            Database.SetInitializer(new InitializerClass());

         }

 

Fluent Configuration

you can define any kind of database field by EF built-in mapping feature, for example about mapping the account 

 

 public class AccountMapping : EntityTypeConfiguration<Account>
    {
        public AccountMapping()
        {
            this.ToTable("Account");
            this.HasKey(a => a.Id);
            this.Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(a => a.Name).IsOptional();
            this.Property(a => a.Balance).IsRequired();
         }
    }

 

 and then you have to add this line of code to your context class in OnModelCreating

 

  modelBuilder.Configurations.Add(new AccountMapping());

 

RelationShips in EF  

You can define one-to-one, one-to-many, many-to-one and many-to-many mapping by entity framework, let's implement them. Add a new class to your Model

 

 public class AccountOwner
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string  Email { get; set; }
        public virtual Account Account { get; set; }
    }

 

And change the Account class like this :

 

 public class Account
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Balance { get; set; }
        public virtual AccountOwner AccountOwner { get; set; }
    }

 

And Change the mapping class of Account like this :

 

 public class AccountMapping : EntityTypeConfiguration<Account>
    {
        public AccountMapping()
        {
            this.ToTable("Account");
            this.HasKey(a => a.Id);
            this.Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(a => a.Name).IsOptional();
            this.Property(a => a.Balance).IsRequired();
            this.HasRequired(a=>a.AccountOwner).WithOptional().WillCascadeOnDelete();
        }
    }

 

And about mapping class of AccountOwner :

 

 public class AccountOwnerMapping : EntityTypeConfiguration<AccountOwner>
    {
        public AccountOwnerMapping()
        {
            this.ToTable("AccountOwner");
            this.HasKey(a => a.Id);
            this.Property(a => a.Id).HasColumnName("AccountOwnerId").HasDatabaseGeneratedOption(
                DatabaseGeneratedOption.Identity);
            this.Property(a => a.Email).HasMaxLength(100).IsRequired();
        }
    }

 

 and in Order to have your mapping class influence in the database you should change the ContextClass :

 

 public class ContextClass : DbContext
    {
        public ContextClass()
        {
            if (this.Database.Exists() && !this.Database.CompatibleWithModel(false))
                this.Database.Delete();
            if (!this.Database.Exists()) this.Database.Create();
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Configurations.Add(new AccountMapping());
            modelBuilder.Configurations.Add(new AccountOwnerMapping());
        }

        public DbSet<Account> Accounts { get; set; }
        public DbSet<AccountOwner> AccountOwners { get; set; }

 

one-to-many 

create these classes 

 

 public class Blog
    {
        public int Id { get; set; }
        public String Title { get; set; }
        public string Text { get; set; }
        public virtual  ICollection<Category> Categories { get; set; }
    }

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

 

Now Add two Mapping class for this Models:

 

 public class CategoryMapping :EntityTypeConfiguration<Category>
    {
        public CategoryMapping()
        {
            this.ToTable("Category");
            this.HasKey(c => c.Id);
            this.Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(c => c.Name);
        }
    }

  public class BlogMapping : EntityTypeConfiguration<Blog>
    {
        public BlogMapping()
        {
            this.ToTable("Blog");
            this.HasKey(b => b.Id);
            this.Property(b => b.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.Property(b => b.Title).IsRequired();
            this.Property(b => b.Text).HasColumnType("text").IsMaxLength().IsOptional().HasColumnName("Text");
            this.HasMany(b=>b.Categories).WithRequired(b=>b.Blog).WillCascadeOnDelete();
        }
    }

 

And just like one to one sample add the blog and category configurations to Context class

 

    public class ContextClass : DbContext
    {
        public ContextClass()
        {
            if (this.Database.Exists() && !this.Database.CompatibleWithModel(false))
                this.Database.Delete();
            if (!this.Database.Exists()) this.Database.Create();
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Configurations.Add(new AccountMapping());
            modelBuilder.Configurations.Add(new AccountOwnerMapping());
            modelBuilder.Configurations.Add(new CategoryMapping());
            modelBuilder.Configurations.Add(new BLogMapping());
        }
        public DbSet<Account> Accounts { get; set; }
        public DbSet<AccountOwner> AccountOwners { get; set; }
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Category> Categories { get; set; }
   }

 

About many to many, create Product class with this definition

 

    public class Product
    {
        public int Id { get; set; }
        public string ProductName { get; set; }
        public decimal Amount { get; set; }
    }

 

And Customer class :

 

  public class Customer
    {
        public int Id { get; set; }
        public string CustomerName { get; set; }
    }

 

And finally ProductCustomer :

 

 public class ProductCustomer
    {
        public virtual Product ProductId { get; set; }
        public virtual Customer CustomerId { get; set; }
    }

 

I think You know how to map Product and Customer, Don’t you !? you could also remove the ProductCustomer Class and change the Customer and Product class to achieve the many to many mapping: 

 

public class Customer
{ 
    public int Id { get; set; }
    public string CustomerName { get; set; }
    public virtual List<Product> Products {get; set;}
 }

 public class Product
 {
    public int Id { get; set; }
    public string ProductName { get; set; }
    public decimal Amount { get; set; }
    public virtual List<Customer> Customers {get;set;}
 }

 

 have a good time!

Category: Software

comments powered by Disqus