اگر با داتنت کار میکنی، احتمالاً اسم Entity Framework به گوشت خورده. ولی شاید هنوز دقیقاً ندونی این ابزار چیه و چرا دنیای برنامهنویسی C# بدون اون ناقصه. خب، بذار خیلی ساده توضیح بدم.
Entity Framework (EF) یک ORM یا Object-Relational Mapper هست که مایکروسافت اون رو ساخته. کار اصلیش اینه که بین دنیای شیءگرای C# و دنیای رابطهای دیتابیس (مثل SQL Server) یه پل ارتباطی ایجاد کنه.
به زبون سادهتر: به جای اینکه تو کدت مستقیم SQL بنویسی، با Entity Framework میتونی با همون کلاسهای C# خودت با دیتابیس حرف بزنی. این یعنی کد تمیزتر، توسعه سریعتر و خطاهای کمتر!
خیلی از کاربران ایرانی میپرسن: «EF Classic با EF Core چه فرقی دارن؟» این سوال مهمیه. بذار واضح توضیح بدم:
توصیه ما؟ اگه پروژه جدید شروع میکنی، حتماً EF Core استفاده کن. این آموزش هم بیشتر روی EF Core تمرکز داره.
برای شروع، باید EF Core رو به پروژهات اضافه کنی. این کار از طریق NuGet Package Manager یا CLI انجام میشه.
در Visual Studio، پنجره Package Manager Console رو باز کن و دستورات زیر رو اجرا کن:
Install-Package Microsoft.EntityFrameworkCore Install-Package Microsoft.EntityFrameworkCore.SqlServer Install-Package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.EntityFrameworkCore dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.EntityFrameworkCore.Tools
EF Core سه رویکرد مختلف داره که باید بشناسیشون:
پرکاربردترین روش! تو اول کلاسهای C# خودت رو مینویسی، بعد EF از روی اونها جدولهای دیتابیس میسازه. این روش کنترل بیشتری به توسعهدهنده میده.
وقتی دیتابیس از قبل وجود داره، EF از روی اون کلاسهای C# میسازه. برای پروژههای Legacy مناسبه.
از طریق طراح گرافیکی، مدل دادهها رو میکشی و EF هم کلاس و هم دیتابیس رو میسازه. امروزه کمتر استفاده میشه.
بذار با یه مثال عملی پیش بریم. فرض کن داریم یه سیستم مدیریت کتابخونه میسازیم.
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public DateTime PublishedDate { get; set; }
public decimal Price { get; set; }
// Navigation Property
public int CategoryId { get; set; }
public Category Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
// Navigation Property
public List Books { get; set; }
}
DbContext قلب Entity Framework هست. این کلاس ارتباط بین کد C# تو و دیتابیس رو مدیریت میکنه.
public class LibraryContext : DbContext
{
public LibraryContext(DbContextOptions options)
: base(options)
{
}
public DbSet Books { get; set; }
public DbSet Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(b => b.Price)
.HasColumnType(“decimal(18,2)”);
modelBuilder.Entity()
.HasOne(b => b.Category)
.WithMany(c => c.Books)
.HasForeignKey(b => b.CategoryId);
}
}
در فایل appsettings.json رشته اتصال به دیتابیس رو تنظیم کن:
{
“ConnectionStrings”: {
“DefaultConnection”: “Server=.;Database=LibraryDB;Trusted_Connection=True;TrustServerCertificate=True;”
}
}
builder.Services.AddDbContext(options => options.UseSqlServer( builder.Configuration.GetConnectionString(“DefaultConnection”) ) );
Migration یکی از قدرتمندترین ویژگیهای EF Core هست. با این ابزار، هر تغییری که تو کلاسهات بدی، بهصورت کنترلشده روی دیتابیس اعمال میشه.
ساخت اولین Migration Add-Migration InitialCreate اعمال Migration روی دیتابیس Update-Database برگشت به Migration قبلی Update-Database PreviousMigrationName حذف آخرین Migration (اگه هنوز اعمال نشده) Remove-Migration
حالا بریم سراغ عملیترین بخش: ایجاد، خواندن، بهروزرسانی و حذف داده.
using (var context = new LibraryContext(options))
{
var book = new Book
{
Title = “برنامهنویسی با C#”,
Author = “علی محمدی”,
PublishedDate = DateTime.Now,
Price = 150000,
CategoryId = 1
};
context.Books.Add(book);
await context.SaveChangesAsync();
}
// خواندن همه کتابها var allBooks = await context.Books .Include(b => b.Category) .ToListAsync(); // فیلتر کردن var cheapBooks = await context.Books .Where(b => b.Price < 200000) .OrderBy(b => b.Title) .ToListAsync(); // یک آیتم خاص var book = await context.Books .FirstOrDefaultAsync(b => b.Id == 1);
var book = await context.Books.FindAsync(1);
if (book != null)
{
book.Price = 180000;
book.Title = “عنوان جدید”;
await context.SaveChangesAsync();
}
var book = await context.Books.FindAsync(1);
if (book != null)
{
context.Books.Remove(book);
await context.SaveChangesAsync();
}
یکی از مهمترین مفاهیمی که باید بلد باشی، روابط بین Entity ها هست.
مثل رابطه Category و Book که بالا دیدیم. یک دستهبندی میتونه چند کتاب داشته باشه.
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public List Courses { get; set; } = new();
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public List Students { get; set; } = new();
}
EF Core 5+ این رابطه رو بدون نیاز به جدول واسط مستقیم مدیریت میکنه!
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public UserProfile Profile { get; set; }
}
public class UserProfile
{
public int Id { get; set; }
public string Bio { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
این سه مفهوم یکی از سوالات رایج در مصاحبههای برنامهنویسی ایرانیه!
⚠️ مشکل N+1 Query
یکی از بزرگترین اشتباهات در کار با EF، مشکل N+1 Query هست. وقتی از Lazy Loading بدون دقت استفاده کنی، برای هر آیتم یه کوئری جداگانه به دیتابیس میزنه. همیشه کوئریهات رو با SQL Profiler بررسی کن!
EF Core ابزارهای عالی برای بهینهسازی داره:
// بهینه: AsNoTracking + Select
var books = await context.Books
.AsNoTracking()
.Where(b => b.CategoryId == 1)
.Select(b => new { b.Id, b.Title, b.Price })
.Skip(0)
.Take(10)
.ToListAsync();
🚀 سایت شما هم میتونه صفحه اول گوگل باشه!
آیا میخواهید سایت شما هم مثل رقبا در صفحه اول گوگل باشد و زنگخورهایتان چند برابر شود؟ سئوی سایت خود را به متخصصان ما بسپارید. همین حالا برای مشاوره رایگان با ما تماس بگیرید:
📞 09190994063 | 09376846692
با Data Annotations میتونی مستقیم روی کلاسهات، قوانین دیتابیس رو تعریف کنی:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Book
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(200)]
[Column(“BookTitle”)]
public string Title { get; set; }
[Required]
[MaxLength(100)]
public string Author { get; set; }
[Column(TypeName = “decimal(18,2)”)]
[Range(0, 10000000)]
public decimal Price { get; set; }
[NotMapped]
public string DisplayName => $“{Title} - {Author}”;
}
دو روش برای تنظیمات مدل وجود داره: Data Annotations (سادهتر ولی محدودتر) و Fluent API (پیچیدهتر ولی قدرتمندتر).
توصیه حرفهای: برای پروژههای بزرگ، از Fluent API در یک فایل جداگانه استفاده کن تا کلاسهای Entity تمیز بمونن.
public class BookConfiguration : IEntityTypeConfiguration{ public void Configure(EntityTypeBuilder builder) { builder.HasKey(b => b.Id); builder.Property(b => b.Title) .IsRequired() .HasMaxLength(200); builder.Property(b => b.Price) .HasColumnType(“decimal(18,2)”); builder.HasIndex(b => b.Author); } }
در پروژههای واقعی، مستقیم از DbContext در Controller استفاده نمیکنیم. به جاش از Repository Pattern استفاده میکنیم تا کد تمیزتر و قابلتستتر بشه.
public interface IBookRepository
{
Task> GetAllAsync();
Task GetByIdAsync(int id);
Task AddAsync(Book book);
Task UpdateAsync(Book book);
Task DeleteAsync(int id);
}
public class BookRepository : IBookRepository
{
private readonly LibraryContext _context;
public BookRepository(LibraryContext context)
{
_context = context;
}
public async Task> GetAllAsync()
{
return await _context.Books
.AsNoTracking()
.Include(b => b.Category)
.ToListAsync();
}
// … سایر متدها
}
بعضی وقتها نیاز داری مستقیم SQL اجرا کنی. EF Core این امکان رو هم داره:
// کوئری SQL با Parameterized Query (امن در برابر SQL Injection)
var books = await context.Books
.FromSqlRaw(“SELECT * FROM Books WHERE Price > {0}”, 100000)
.ToListAsync();
// اجرای دستورات SQL
await context.Database.ExecuteSqlRawAsync(
“UPDATE Books SET Price = Price * 1.1 WHERE CategoryId = {0}”, 1
);
💡 یه نکته مهم از تیم ما:
همونطور که یادگیری Entity Framework به پروژههای نرمافزاریت رونق میده، سئوی حرفهای هم به کسبوکار آنلاینت رونق میده. سایتی که در گوگل دیده نشه، مثل مغازهایه که تابلو نداره!
آیا میخواهید سایت شما هم مثل رقبا در صفحه اول گوگل باشد و زنگخورهایتان چند برابر شود؟ سئوی سایت خود را به متخصصان ما بسپارید. همین حالا برای مشاوره رایگان با ما تماس بگیرید: 09190994063 - 09376846692
بله، Entity Framework Core در پروژههای Enterprise بزرگ هم استفاده میشه. با رعایت نکات بهینهسازی مثل AsNoTracking، Pagination، ایندکسگذاری مناسب و استفاده از Compiled Queries، میتونی به عملکرد بسیار خوبی برسی. شرکتهای بزرگ دنیا از EF Core در محصولاتشون استفاده میکنن.
Dapper یک Micro-ORM هست که سرعت بالاتری داره ولی باید SQL بیشتری بنویسی. EF Core راحتتر و پرامکاناتتره. برای پروژههای معمولی EF Core بهتره. برای کوئریهای بسیار پیچیده و حساس به سرعت، میتونی از هر دو همزمان استفاده کنی.
کاملاً! EF Core از چندین دیتابیس پشتیبانی میکنه. برای MySQL از Pomelo.EntityFrameworkCore.MySql، برای PostgreSQL از Npgsql.EntityFrameworkCore.PostgreSQL و برای SQLite از Microsoft.EntityFrameworkCore.Sqlite استفاده کن. فقط کافیه Provider رو عوض کنی، بقیه کد تغییری نمیکنه.
چند روش داری: ۱) از LogTo در تنظیمات DbContext استفاده کن تا SQL ها در Console لاگ بشه. ۲) از SQL Server Profiler یا Azure Data Studio استفاده کن. ۳) در EF Core 5+، متد ToQueryString() رو روی IQueryable فراخوانی کن تا SQL تولیدی رو ببینی. ۴) ابزار MiniProfiler برای وب خیلی مفیده.
بهترین روش استفاده از Global Query Filter هست. یک فیلد IsDeleted به Entity ات اضافه کن، بعد در DbContext با modelBuilder.Entity.HasQueryFilter(x => !x.IsDeleted) تنظیم کن. از این به بعد EF Core بهطور خودکار رکوردهای حذفشده رو از کوئریها حذف میکنه. برای Override کردن این فیلتر از IgnoreQueryFilters() استفاده کن.
قطعاً! EF Core و ASP.NET Core Web API عالی با هم کار میکنن. EF Core رو از طریق Dependency Injection ثبت میکنی، بعد از طریق Constructor Injection در Repository یا Service هات ازش استفاده میکنی. این ترکیب رایجترین استک برنامهنویسی بکاند در دنیای .NET هست.