📜  ef 核心分离实体 - C# (1)

📅  最后修改于: 2023-12-03 15:14:50.933000             🧑  作者: Mango

EF 核心分离实体 - C#

Introduction

Entity Framework (EF) is a popular Object-Relational Mapping (ORM) framework developed by Microsoft. EF Core is a lightweight, modular and cross-platform version of EF. In this tutorial, we will explore the concept of separating entities from the EF Core DbContext using C#.

Separating Entities from DbContext

In EF Core, a DbContext is a class that represents a database session and allows us to perform CRUD (Create, Read, Update, Delete) operations on the database. Usually, we define our entities as nested classes inside the DbContext like this:

public class MyDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }

    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Order> Orders { get; set; }
    }

    public class Order
    {
        public int Id { get; set; }
        public DateTime OrderDate { get; set; }
        public int CustomerId { get; set; }
        public Customer Customer { get; set; }
    }
}

Although this approach works well for small projects, it can become difficult to maintain as the project grows larger. The DbContext class becomes bloated with all the entity definitions.

To address this problem, we can separate the entity classes from the DbContext class. Here's how we can do it:

Create a separate project for the entity classes. Let's call it "MyProject.Entities".

Add a reference to the "MyProject.Entities" project from the DbContext class project.

Define the entity classes in the "MyProject.Entities" project:

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public DateTime OrderDate { get; set; }
    public int CustomerId { get; set; }
    public Customer Customer { get; set; }
}

Remove the nested entity classes from the DbContext class:

public class MyDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }
}

Configure the DbContext to use the entity classes:

public class MyDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(MyDbContext).Assembly);
    }
}

This code tells EF Core to look for entity configurations in the same assembly as the DbContext class. We'll create the entity configurations shortly.

Create a separate project for the entity configurations. Let's call it "MyProject.EntityConfigurations".

Add a reference to the "MyProject.EntityConfigurations" project from the DbContext class project.

Define the entity configurations in the "MyProject.EntityConfigurations" project:

public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        builder.HasKey(e => e.Id);
        builder.Property(e => e.Name).IsRequired().HasMaxLength(50);
        builder.HasMany(e => e.Orders).WithOne(e => e.Customer);
    }
}

public class OrderConfiguration : IEntityTypeConfiguration<Order>
{
    public void Configure(EntityTypeBuilder<Order> builder)
    {
        builder.HasKey(e => e.Id);
        builder.Property(e => e.OrderDate).IsRequired();
        builder.HasOne(e => e.Customer).WithMany(e => e.Orders).HasForeignKey(e => e.CustomerId).OnDelete(DeleteBehavior.Cascade);
    }
}

These configurations specify how the database should map the entity classes. For example, the CustomerConfiguration specifies that the Id property is the primary key, the Name property is required and has a maximum length of 50, and the Orders property is a navigation property that references multiple Order entities.

Configure the DbContext to use the entity configurations:

public class MyDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Order> Orders { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(MyDbContext).Assembly);
    }
}

This code tells EF Core to apply the entity configurations found in the same assembly as the DbContext class.

Conclusion

Separating entities from the DbContext class can help make the code easier to maintain as the project grows larger. By using separate projects for the entities and configurations, we can also achieve better separation of concerns.