سری بررسی SQL Smell در EF Core - ایجاد روابط Polymorphic - بخش اول
نویسنده: سیروان عفیفی
تاریخ: ۱۳۹۹/۰۵/۰۸ ۲۳:۳۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
public enum CommentType
{
Article,
Video,
Event
}
public class Comment
{
public int Id { get; set; }
public string CommentText { get; set; }
public string User { get; set; }
public int? TypeId { get; set; }
public CommentType CommentType { get; set; }
}
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
}
public class Video
{
public int Id { get; set; }
public string Url { get; set; }
public string Description { get; set; }
}
public class Event
{
public int Id { get; set; }
public string Name { get; set; }
public DateTimeOffset? Start { get; set; }
public DateTimeOffset? End { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<Article> Articles { get; set; }
public DbSet<Video> Videos { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<Comment> Comments { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=polymorphic.db");
} var articleComments = dbContext.Comments
.Where(x => x.CommentType == CommentType.Article && x.TypeId.Value == 1);
foreach (var articleComment in articleComments)
{
Console.WriteLine(articleComment.CommentText);
}
public class Comment
{
public int Id { get; set; }
public string CommentText { get; set; }
public string User { get; set; }
public virtual ICollection<ArticleComment> ArticleComments { get; set; }
public virtual ICollection<VideoComment> VideoComments { get; set; }
public virtual ICollection<EventComment> EventComments { get; set; }
}
public class Article
{
public Article()
{
ArticleComments = new HashSet<ArticleComment>();
}
public int Id { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public virtual ICollection<ArticleComment> ArticleComments { get; set; }
}
public class Video
{
public Video()
{
VideoComments = new HashSet<VideoComment>();
}
public int Id { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public virtual ICollection<VideoComment> VideoComments { get; set; }
}
public class Event
{
public Event()
{
EventComments = new HashSet<EventComment>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTimeOffset? Start { get; set; }
public DateTimeOffset? End { get; set; }
public virtual ICollection<EventComment> EventComments { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<Article> Articles { get; set; }
public DbSet<ArticleComment> ArticleComments { get; set; }
public DbSet<Video> Videos { get; set; }
public DbSet<VideoComment> VideoComments { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<EventComment> EventComments { get; set; }
public DbSet<Comment> Comments { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=polymorphic.db");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ArticleComment>(entity =>
{
entity.HasKey(e => new { e.CommentId, e.ArticleId })
.HasName("PK_dbo.ArticleComments");
entity.HasIndex(e => e.ArticleId)
.HasName("IX_ArticleId");
entity.HasIndex(e => e.CommentId)
.HasName("IX_ArticleCommentId");
entity.HasOne(d => d.Article)
.WithMany(p => p.ArticleComments)
.HasForeignKey(d => d.ArticleId)
.HasConstraintName("FK_dbo.ArticleComments_dbo.Articles_ArticleId");
entity.HasOne(d => d.Comment)
.WithMany(p => p.ArticleComments)
.HasForeignKey(d => d.CommentId)
.HasConstraintName("FK_dbo.ArticleComments_dbo.Comments_CommentId");
});
modelBuilder.Entity<VideoComment>(entity =>
{
entity.HasKey(e => new { e.CommentId, e.VideoId })
.HasName("PK_dbo.VideoComments");
entity.HasIndex(e => e.VideoId)
.HasName("IX_VideoId");
entity.HasIndex(e => e.CommentId)
.HasName("IX_VideoCommentId");
entity.HasOne(d => d.Video)
.WithMany(p => p.VideoComments)
.HasForeignKey(d => d.VideoId)
.HasConstraintName("FK_dbo.VideoComments_dbo.Videos_VideoId");
entity.HasOne(d => d.Comment)
.WithMany(p => p.VideoComments)
.HasForeignKey(d => d.CommentId)
.HasConstraintName("FK_dbo.VideoComments_dbo.Comments_CommentId");
});
modelBuilder.Entity<EventComment>(entity =>
{
entity.HasKey(e => new { e.CommentId, e.EventId })
.HasName("PK_dbo.EventComments");
entity.HasIndex(e => e.EventId)
.HasName("IX_EventId");
entity.HasIndex(e => e.CommentId)
.HasName("IX_EventCommentId");
entity.HasOne(d => d.Event)
.WithMany(p => p.EventComments)
.HasForeignKey(d => d.EventId)
.HasConstraintName("FK_dbo.EventComments_dbo.Events_EventId");
entity.HasOne(d => d.Comment)
.WithMany(p => p.EventComments)
.HasForeignKey(d => d.CommentId)
.HasConstraintName("FK_dbo.EventComments_dbo.Comments_CommentId");
});
}
} var article = new Article
{
Title = "Article A",
Slug = "article_a",
Description = "No Description"
};
var comment = new Comment
{
CommentText = "It's great",
User = "Sirwan"
};
dbContext.ArticleComments.Add(new ArticleComment
{
Article = article,
Comment = comment
});
dbContext.SaveChanges();
var articleOne = dbContext.Articles
.Include(article => article.ArticleComments)
.ThenInclude(comment => comment.Comment)
.First(article => article.Id == 1);
var article1Comments = articleOne.ArticleComments.Select(x => x.Comment);
Console.WriteLine(article1Comments.Count());
public class Comment
{
public int Id { get; set; }
public string CommentText { get; set; }
public string User { get; set; }
// Article
public virtual Article Article { get; set; }
public int? ArticleId { get; set; }
// Video
public virtual Video Video { get; set; }
public int? VideoId { get; set; }
// Event
public virtual Event Event { get; set; }
public int? EventId { get; set; }
}
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Video
{
public int Id { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Event
{
public int Id { get; set; }
public string Name { get; set; }
public DateTimeOffset? Start { get; set; }
public DateTimeOffset? End { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<Article> Articles { get; set; }
public DbSet<Video> Videos { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<Comment> Comments { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=polymorphic.db");
} protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Comment>(entity =>
entity.HasCheckConstraint("CHECK_FKs",
"(`ArticleId` IS NOT NULL) AND (`VideoId` IS NOT NULL) AND (`EventId` IS NOT NULL)"));
} var articles = dbContext.Articles
.Include(x => x.Comments).Where(x => x.Id == 1);
foreach (var article in articles)
{
Console.WriteLine($"{article.Title} - Comments: {article.Comments.Count}");
}
var comment = dbContext.Comments.Include(x => x.Article)
.FirstOrDefault(x => x.Id == 1);
Console.WriteLine(comment?.Article.Title);