MSDN Documentation

Working with Data

This section delves into the practical aspects of interacting with your data using Entity Framework. We'll cover common operations like creating, reading, updating, and deleting (CRUD) entities, as well as managing relationships and handling concurrency.

CRUD Operations

Entity Framework simplifies data manipulation through its DbContext and entity objects. The following operations demonstrate basic CRUD:

Creating a New Entity

To add a new record, create an instance of your entity class and add it to the appropriate DbSet within your DbContext.


using (var context = new YourDbContext())
{
    var newProduct = new Product
    {
        Name = "New Gadget",
        Price = 99.99m
    };
    context.Products.Add(newProduct);
    context.SaveChanges();
}
            

Reading Entities

You can retrieve entities using LINQ queries against your DbSets. Entity Framework translates these queries into SQL.


using (var context = new YourDbContext())
{
    var product = context.Products.FirstOrDefault(p => p.Id == 1);
    if (product != null)
    {
        Console.WriteLine($"Product Name: {product.Name}");
    }

    var allProducts = context.Products.ToList();
}
            

Updating an Entity

Modify the properties of an entity retrieved from the context, and then call SaveChanges(). Entity Framework tracks these changes automatically.


using (var context = new YourDbContext())
{
    var productToUpdate = context.Products.Find(1);
    if (productToUpdate != null)
    {
        productToUpdate.Price = 109.99m;
        context.SaveChanges();
    }
}
            

Deleting an Entity

To remove an entity, retrieve it first and then call the Remove() method on the DbSet.


using (var context = new YourDbContext())
{
    var productToDelete = context.Products.Find(1);
    if (productToDelete != null)
    {
        context.Products.Remove(productToDelete);
        context.SaveChanges();
    }
}
            

Managing Relationships

Entity Framework supports various relationships, including one-to-many, many-to-many, and one-to-one. When you load an entity, related entities can often be loaded implicitly or explicitly.

Loading Related Data (Eager Loading, Lazy Loading, Explicit Loading)

Concurrency Handling

Concurrency occurs when multiple users try to modify the same data simultaneously. Entity Framework provides mechanisms to detect and resolve these conflicts.

Optimistic Concurrency

This is the most common approach. It involves versioning or timestamping data. If the data has changed since it was last read, an exception is thrown.

To implement optimistic concurrency, mark a property in your entity with the [ConcurrencyCheck] attribute or configure it in OnModelCreating. When SaveChanges fails due to a concurrency conflict, a DbUpdateConcurrencyException is thrown.


// In your entity
public class Product
{
    public int Id { get; set; }
    [ConcurrencyCheck]
    public byte[] RowVersion { get; set; } // Or DateTime Stamp
    public string Name { get; set; }
    public decimal Price { get; set; }
}

// Handling the exception
try
{
    context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
    // Handle the concurrency conflict, e.g., reload data and reapply changes
    var entry = ex.Entries.Single();
    var databaseValues = entry.GetDatabaseValues();

    if (databaseValues == null)
    {
        // The entity was deleted by another user
        Console.WriteLine("The entity has been deleted by another user.");
    }
    else
    {
        // Reload the original and database values
        var databaseEntry = entry.ToRow(databaseValues);
        var clientValues = (Product)entry.Entity;

        // Compare the client's values with the database's values
        if (databaseEntry.Name != clientValues.Name)
            Console.WriteLine("The product name has been changed by another user.");
        if (databaseEntry.Price != clientValues.Price)
            Console.WriteLine("The product price has been changed by another user.");

        // Refresh original values and re-attach the entity
        entry.OriginalValues.SetValues(databaseValues);
        Console.WriteLine("Concurrency conflict detected and handled.");
        // Optionally, re-throw or prompt user for resolution
    }
}