مباحث تکمیلی مدلهای خود ارجاع دهنده در EF Code first
نویسنده: وحید نصیری
تاریخ: ۱۳۹۱/۰۵/۱۳ ۱۴:۲۴
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
namespace EFGeneral
{
public class BlogComment
{
public int Id { set; get; }
[MaxLength]
public string Body { set; get; }
public virtual BlogComment Reply { set; get; }
public int? ReplyId { get; set; }
public ICollection<BlogComment> Children { get; set; }
}
public class MyContext : DbContext
{
public DbSet<BlogComment> BlogComments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Self Referencing Entity
modelBuilder.Entity<BlogComment>()
.HasOptional(x => x.Reply)
.WithMany(x => x.Children)
.HasForeignKey(x => x.ReplyId)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
}
public class Configuration : DbMigrationsConfiguration<MyContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(MyContext context)
{
var comment1 = new BlogComment { Body = "نظر من این است که" };
var comment12 = new BlogComment { Body = "پاسخی به نظر اول", Reply = comment1 };
var comment121 = new BlogComment { Body = "پاسخی به پاسخ به نظر اول", Reply = comment12 };
context.BlogComments.Add(comment121);
base.Seed(context);
}
}
public static class Test
{
public static void RunTests()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>());
using (var ctx = new MyContext())
{
var list = ctx.BlogComments
//.where ...
.ToList() // fills the childs list too
.Where(x => x.Reply == null) // for TreeViewHelper
.ToList();
if (list.Any())
{
}
}
}
}
}
public class BlogComment
{
// ...
public ICollection<BlogComment> Children { get; set; }
}
private void AppendChildren(TagBuilder parentTag, T parentItem, Func<T, IEnumerable<T>> childrenProperty)
{
var children = childrenProperty(parentItem);
if (children == null || !children.Any())
{
return;
}
//...
public class Person
{
// other properties
[Required]
public virtual Person RelatedPerson {get; set;}
}
CREATE TABLE [dbo].[Tree]( [Id] [int] IDENTITY(1,1) NOT NULL, [Name] [nchar](10) NOT NULL, [ParentId] [int] NOT NULL, CONSTRAINT [PK_Tree] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE [dbo].[Tree] WITH CHECK ADD CONSTRAINT [FK_Tree_Tree] FOREIGN KEY([ParentId]) REFERENCES [dbo].[Tree] ([Id]) GO ALTER TABLE [dbo].[Tree] CHECK CONSTRAINT [FK_Tree_Tree] GO
INSERT INTO [Tree]
([Name]
,[ParentId])
VALUES
('12'
,2)
var model = _efComment.List(p => p.PostId == postId); var list = model.ToList() .Where(p => p.ComentStatus == ComentStatus.Ok) .Where(x => x.Reply == null) .ToList();
p => p.PostId == postId && p.ComentStatus == ComentStatus.Ok
public class Page
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual DateTime? CreatedDate { get; set; }
public virtual DateTime? ModifiedDate { get; set; }
public virtual string Body { get; set; }
public virtual string Keyword { get; set; }
public virtual string Description { get; set; }
public virtual string Status { get; set; }
public virtual bool? CommentStatus { get; set; }
public virtual int? Order { get; set; }
public virtual User User { get; set; }
public virtual User EditedByUser { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual int? ParentId { get; set; }
public virtual Page Parent { get; set; }
public virtual ICollection<Page> Children { get; set; }
}this._pages.ToList().Where(page => page.Parent == null).ToList();
SELECT [Extent1].[Id] AS [Id], [Extent1].[Title] AS [Title], [Extent1].[CreatedDate] AS [CreatedDate], [Extent1].[ModifiedDate] AS [ModifiedDate], [Extent1].[Body] AS [Body], [Extent1].[Keyword] AS [Keyword], [Extent1].[Description] AS [Description], [Extent1].[Status] AS [Status], [Extent1].[CommentStatus] AS [CommentStatus], [Extent1].[Order] AS [Order], [Extent1].[ParentId] AS [ParentId], [Extent2].[Id] AS [Id1], [Extent2].[Title] AS [Title1], [Extent2].[CreatedDate] AS [CreatedDate1], [Extent2].[ModifiedDate] AS [ModifiedDate1], [Extent2].[Body] AS [Body1], [Extent2].[Keyword] AS [Keyword1], [Extent2].[Description] AS [Description1], [Extent2].[Status] AS [Status1], [Extent2].[CommentStatus] AS [CommentStatus1], [Extent2].[Order] AS [Order1], [Extent2].[ParentId] AS [ParentId1], [Extent2].[User_Id] AS [User_Id], [Extent2].[EditedByUser_Id] AS [EditedByUser_Id], [Extent1].[User_Id] AS [User_Id1], [Extent1].[EditedByUser_Id] AS [EditedByUser_Id1] FROM [dbo].[Pages] AS [Extent1] LEFT OUTER JOIN [dbo].[Pages] AS [Extent2] ON [Extent1].[ParentId] = [Extent2].[Id
SELECT [Extent1].[Id] AS [Id], [Extent1].[Body] AS [Body], [Extent1].[ReplyId] AS [ReplyId] FROM [dbo].[BlogComments] AS [Extent1]
this._pages.Include(page => page.Children).ToList().Where(page => page.Parent == null).ToList();
public class NavBarModel
{
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual string Status { get; set; }
public virtual int? Order { get; set; }
public virtual NavBarModel Parent { get; set; }
public virtual ICollection<Page> Children { get; set; }
}@model IEnumerable<DomainClasses.Page>
@helper ShowNavBar(IEnumerable<DomainClasses.Page> pages)
{
foreach (var page in pages)
{
if (page != null)
{
if (page.Children.Count == 0)
{
<text><li><a tabindex="-1" href="#">@page.Title</a></li></text>
}
if (page.Children.Count > 0 && page.Parent == null)
{
<text><li class="dropdown"><a class="dropdown-toggle" id="dLabel" role="button" data-toggle="dropdown" data-target="#" href="/page.html">@page.Title<b class="caret"></b></a><ul class="dropdown-menu" role="menu" aria-labelledby="dLabel"><li><a tabindex="-1" href="#">@page.Title</a></li></text>
@ShowNavBar(page.Children)
@:</ul></li>
}
if (page.Children.Count > 0 && page.Parent != null)
{
<text><li class="dropdown-submenu"><a tabindex="-1" href="#">@page.Title</a><ul class="dropdown-menu"></text>
@ShowNavBar(page.Children)
@:</ul></li>
}
}
}
}
<div class="navbar" style="margin-bottom: 10px;">
<div class="navbar-inner">
<a class="brand" href="www.google.com">IT-EBOOK</a>
<ul class="nav">
<li class="active"><a href="#">خانه</a></li>
<li><a href="#">ورود</a></li>
@ShowNavBar(Model)
<li><a href="#">ارتباط با ما</a></li>
</ul>
<div class="input-append pull-left visible-desktop" style="margin-top: 5px;">
<input class="span6 search-input" id="Text1" type="text">
<button class="btn btn-primary" type="button">جست و جو</button>
<button class="btn btn-info btn-advanced-search" type="button">پیشرفته</button>
</div>
</div>
</div>var list = context.BlogComment.Where(p => p.UserId == 100)
.Select(p => p.Body, p.Id, p.Children)
.ToList(); public partial class BlogComment
{
public BlogComment()
{
this.Children = new HashSet<BlogComment>();
}
public int Id { get; set; }
public string Body { get; set; }
public Nullable<System.DateTime> DateSend { get; set; }
public Nullable<System.DateTime> DateRead { get; set; }
public bool IsDeleted { get; set; }
public int UserId { get; set; }
[Newtonsoft.Json.JsonIgnore]
public virtual BlogComment Reply { get; set; }
public int? ReplyId { get; set; }
public virtual ICollection<BlogComment> Children { get; set; }
}public JsonNetResult Index()
{
var ctx = new testEntities();
var list = ctx.BlogComments
.Where(p => p.Id == 1)
.Select(p => new
{
p.Id,
p.Body,
p.Children
})
.ToList();
JsonNetResult jsonNetResult = new JsonNetResult();
jsonNetResult.Formatting = Formatting.Indented;
jsonNetResult.SerializerSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
jsonNetResult.Data = list;
return jsonNetResult;
}
The DELETE statement conflicted with the SAME TABLE REFERENCE constraint
DECLARE @Table TABLE(
ID INT,
ParentID INT,
NAME VARCHAR(20)
)
INSERT INTO @Table (ID,ParentID,[NAME]) SELECT 1, NULL, 'A'
INSERT INTO @Table (ID,ParentID,[NAME]) SELECT 2, 1, 'B-1'
INSERT INTO @Table (ID,ParentID,[NAME]) SELECT 3, 1, 'B-2'
INSERT INTO @Table (ID,ParentID,[NAME]) SELECT 4, 2, 'C-1'
INSERT INTO @Table (ID,ParentID,[NAME]) SELECT 5, 2, 'C-2'
DECLARE @ID INT
SELECT @ID = 2
;WITH ret AS(
SELECT*
FROM@Table
WHEREID = @ID
UNION ALL
SELECTt.*
FROM@Table t INNER JOIN
ret r ON t.ParentID = r.ID
)
SELECT *
FROM retvar specifiedCommentId = 4; //عدد 4 در اینجا شماره رکورد کامنتی است که دارای یک سری زیر کامنت است
var list = ctx.BlogComments
.Include(x => x.Reply)
.Where(x => x.Id >= specifiedCommentId && (x.ReplyId == x.Reply.Id || x.Reply == null))
.ToList() // fills the childs list too
.Where(x => x.Reply == null) // for TreeViewHelper
.ToList();GroupRoot {id=1, Name="گروه اصلی",ParentId=null}
Group2 {id=2, Name="بازرگانی",ParentId=1}
Group3 {id=3, Name="فروش",ParentId=2}
Group4 {id=4, Name="فروش قطعات",ParentId=3}
Group5 {id=5, Name="خدمات",ParentId=1}
person1 {name="Ali", GroupId=2}//بازرگانی
person2 {name="reza", GroupId=3}//فروش
person3 {name="iman", GroupId=3}//فروش
person4 {name="hamid",GroupId=4}//فروش قطعات
person5 {name="hasan",GroupId=4}//فروش قطعات
person6 {name="Ahmad",GroupId=5}//خدمات
person7 {name="vahid",GroupId=1}//گروه اصلیSELECT [Extent1].[Id] AS [Id],
[Extent1].[Body] AS [Body],
[Extent1].[ReplyId] AS [ReplyId],
[Extent2].[Id] AS [Id1],
[Extent2].[Body] AS [Body1],
[Extent2].[ReplyId] AS [ReplyId1]
FROM [dbo].[BlogComments] AS [Extent1]
LEFT OUTER JOIN
[dbo].[BlogComments] AS [Extent2]
ON [Extent1].[ReplyId] = [Extent2].[Id]
WHERE ([Extent1].[Id] >= 2)
AND (([Extent1].[ReplyId] = [Extent1].[ReplyId])
OR (([Extent1].[ReplyId] IS NULL)
AND ([Extent1].[ReplyId] IS NULL))
OR ([Extent2].[Id] IS NULL));
public void Remove(int id)
{
var selectedComment = _comments.Find(id);
_comments.Where(x => x.ParentId == id).Load();
_comments.Remove(selectedComment);
}private Stack<Group> GetChildsAndRoot(Group group)
{
var stack = new Stack<Group>();
var queue = new Queue<Group>();
stack.Push(group);
queue.Enqueue(group);
while (queue.Any())
{
var currGroup = queue.Dequeue();
foreach (var child in currGroup.Childs)
{
queue.Enqueue(child);
stack.Push(child);
}
}
return stack;
}var group = _groupRepository.GetByID(id);
var nodes = GetChildsAndRoot(group);
while (nodes.Any())
{
_groupRepository.Delete(nodes.Pop());
}
_unitOfWork.SaveChanges();var query = _tEntities.AsNoTracking()
.Where(p => p.Parent_Id == null && p.IsActive == true)
.OrderBy(sortExpression);
var result = query.ToList();
return result; base.OnModelCreating(modelBuilder);
modelBuilder.Entity<BlogComment>()
.HasOne(x => x.Reply)
.WithMany(x => x.Children)
.HasForeignKey(x => x.ReplyId)
.OnDelete(DeleteBehavior.SetNull);