1399-10-05 09:31 پیاده سازی جدول دیتابیس در Treeview
zahmah

 
سلام
من یک برنامه با سی شارپ 2013 و اس کیوال 2014 نوشته ام که نحوه اتصالم به بانک نیز روش Entity model است. نمونه ای از کد:
var Qsearch=Mydb.tbl_Position.ToList();
foreach ( var pos in Qsearch)
{
if(pos.Country == lstCountry.Text)
lstPosition.Items.Add(pos.Pos_Name_Fa);
}

یک Treeview دارم که میخواهم نودهایش را از جدول بانک اطلاعاتی بگیرد که در نحوه پیاده سازی آن مشکلاتی دارم:
1. وقتی روی نود کلیک میکنم تمام نودهای Parent آن را تا ریشه به من برگرداند(در یک حلقه)
2. وقتی روی نود کلیک میکنم فیلد متناظر آن در دیتابیس را برای من پیدا کند
3. در این جستجو من با عبارت پیدا شده کاری ندارم بلکه از فیلد دیگری که واژه معادل لاتین آن است کار دارم
4. نحوه جستجوی سراسری یک Treeview به چه نحو است؟ و آیا با اندیس دو بعدی و بیشتر می توان به نودها دسترسی داشت
5. بهترین راه برای پیاده سازی Treeview در بانک اطلاعاتی چیست؟ راستش من برای هر سطح نودها یک جدول ساخته ام یعنی برای ریشه یک جدول برای لایه اول زیر ریشه یک جدول و به همین ترتیب...
6. یک رفرنس بسیار خوب معرفی می کنید؟ جستجوهایی که کردم هیچکدام از Entity model استفاده نکرده بودند
ممنون میشوم راهنمایی بفرمائید.
1399-10-06 21:56
حاجی شریفی
مؤسس سایت
 
سلام
نقل قول نوشته شده توسط: zahmah
وقتی روی نود کلیک میکنم تمام نودهای Parent آن را تا ریشه به من برگرداند

این موارد که بسیار ساده است
private  IList<TreeNode> GetAllParents(TreeNode child)
{
var list = new List<TreeNode>() ;
while (child != null )
{
list.Add(child) ;
child = child.Parent ;
}
list.Reverse() ;
return list ;
}


نقل قول نوشته شده توسط: zahmah
وقتی روی نود کلیک میکنم فیلد متناظر آن در دیتابیس را برای من پیدا کند

کافی است در زمان Add گره جدید به درخت خصیصه Tag را با سطر جاری دیتابیس پر کنید .
این خصیصه یک object گرفته و همیشه همراه گره نگهداری میکند
دات نت و سی شارپ از این خصیصه استفاده نمیکنند و پردازش و کاری روی آن انجام نمیدهند
مانند یک کیسه(Bag) یا برچسب(Tag) همیشه همراه شیء گره است و شما میتوانید هر چیزی در آن قرار دهید !
همانطورکه عرض کردم، کافی است سطر Entity متناظر با گره را در آن قرار دهید تا همیشه همراه گره باشد و به تمام فیلدهای مربوطه دسترسی داشته باشید

زمان ایجاد و افزودن گره
var  child = new  TreeNode()
{
Text = dbRow.Text,
Tag = dbRow
};
parent.Nodes.Add(child) ;


زمان نیاز به خواندن اطلاعات
private void  treeView1_NodeMouseClick(object  sender, TreeNodeMouseClickEventArgs e)
{
var dbRow = (YOUR_ENTITY_ROW_TYPE)e.Node.Tag ;
var firstName = dbRow.FirstName;
var lastName = dbRow.LastName;
var birthDate = dbRow.BirthDate;
...

نوع YOUR_ENTITY_ROW_TYPE در واقع نام کلاس سطر Entity شما است، همان چیزی که در Tag ریخته بودید، نمیدانم بطور مثال OrganizationalUnitEntityRow یا CustomerEntityRow !

نقل قول نوشته شده توسط: zahmah
در این جستجو من با عبارت پیدا شده کاری ندارم بلکه از فیلد دیگری که واژه معادل لاتین آن است کار دارم

درست متوجه نشدم ... میخواهد در Tree جستجو کنید؟ یا منظورتان همان بود که با کلیک روی گره ، فیلدهای دیگر را داشته باشید؟
جستجو در درخت میتواند شبیه این باشد و داشتن همه فیلدها را هم که قبل تر توضیح دادم

private void  DeepSearch(TreeNode parent, IList<TreeNode> buffer, string  search)
{
foreach (TreeNode child in parent.Nodes)
{
this .DeepSearch(child, buffer, search) ;
var dbRow = (YOUR_ENTITY_ROW_TYPE)child.Tag ;
if (string .IsNullOrEmpty(dbRow.YOUR_FIELD_NAME)) continue ;
if (dbRow.YOUR_FIELD_NAME.IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0) continue ;
buffer.Add(child);
}
}

public IList<TreeNode> DeepSearch(string search)
{
var list = new List<TreeNode>();
if (string .IsNullOrEmpty(search)) return list ;
foreach (TreeNode child in this .treeView1.Nodes)
{
this .DeepSearch(child, list, search) ;
}
return list ;
}

...{
var result = this.DeepSearch("text-for-search") ;
}


نقل قول نوشته شده توسط: zahmah
بهترین راه برای پیاده سازی Treeview در بانک اطلاعاتی چیست؟

یک جدول تک برای پیاده سازی یک درخت درون دیتابیس کافی است.
همین سامانه یک جدوله بهترین حالت برای یک درخت است و تا بی نهایت عمق را هم میتوانید پشتیبانی کنید

باید یک کلید خارجی به همان جدول داشته باشید که پدر هر فیلد را نگهداری کند.
برای گره های ریشه (فاقد پدر) فیلد مذکور میتواند null باشد که مشخص کننده بی-پدر=بی-والد بودن گره است.
| ID | ParentID |   Text   | ...other fields ...
-------------------------------------------------
| 1 | null | "root" | ...
| 2 | 1 | "child1" | ...
| 3 | 1 | "child2" | ...
| 4 | 4 | "child3" | ...
1399-10-06 22:24 منبع یادگیری دات نت و Entity Framework
حاجی شریفی
مؤسس سایت
 
نقل قول نوشته شده توسط: zahmah
یک رفرنس بسیار خوب معرفی می کنید؟

درحال حاضر Entity Framework-CodeFirst بیشتر کاربرد دارد و استفاده میشود .
پیشنهاد میکنم Visual Studio 2019 نصب کنید و به سمت استفاده از Entity Framework Core 5 بروید .

هم در پروژه های قدیمی Net Framework و هم بستر جدید Net Core قابل استفاده است
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.SqlServer

شاید حرف و مثالم خوب نباشد ولی همیشه گفته ام که، برای وقت گذاشتن و یادگیری بهتر است ماشین سواری یاد بگیرید تا اسب سواری
EF تکنولوژی روز ORM ها در دات نت است.

در خصوص منابع لاتین ، بطور معمول این منابع بروز و بسیار ساده در اینترنت در دسترس است.
شما میتوانید PDF های باکیفیت با تهیه و نشر حرفه ای را به راحتی بصورت رایگان و یا با نقض کپی رایت (!) در اینترنت پیدا کنید.

ولی منابع فارسی بطور معمول کمی بروز نیستند و تاخیر زمانی نسبت به نسخه های روز دنیا دارند و آنلاین هم موجود نیستند و باشند هم رایگان نیستند.
برای منابع اینترنتی چند سایت وجود دارد که فیلم های آموزشی تهیه و به فروش میرساند که میتوانید به آنها مراجعه کنید مانند toplearn و faradars و...
ولی گمانم همچنان طرفدار کتابهای کاغذی هستم ! کتابها مطالب بسیار بیشتری را با هزینه کمتری به شما منتقل میکنند.
نه اینکه فیلم های آموزشی بد هستند ولی حداقل آن است که نباید خودتان را محدود به یک سایت و یک نوع منبع کنید.
کتاب هم یک منبع غنی و بسیار خوب است، فیلم آموزشی هم یک منبع سریع برای کوتاه مدت است.
متاسفانه امسال نمایشگاه کتاب برگذار نشد و مشغله کاری هم مزید علت شد و گمانم 18 ماهی میشود از بازار نشر و کتاب های روز بی اطلاع هستم .

ولی یادم است که چند سال قبل یک کتاب کوچکی با عنوان Entity Framework 4 دیدم ، این خیلی قدیمی است.
اما نشان میدهد که بخواهید کتاب هم وجود دارد.
میتوانید سری هم به سایت ناشران این حوزه مانند کانون نشر علوم و نص و ناقوس و... بزنید و در کتابهای آنها هم جستجویی داشته باشید ولی خودم الآن جستجوکردم و چیزی نیافتم، بظاهر دیتابیس خیلی محدودی دارند و یا کتاب های موجودشان خیلی کم است !!! یعنی از آن فهرست های بزرگ و پر زرق و برق خبری نیست !

سایت آدینه بوک هم بد نیست، دیتابیس و موتور جستجو خوبی دارد.
بطور نمونه جستجوکردم و این کتاب EF6 را از انتشارات پندار پارس پیدا کردم ، بنظر گزینه قابل قبولی است.
Entity Framework 6 Code First
شب خوش و موفق باشید.
1399-10-07 23:10
zahmah

 
نقل قول
کافی است در زمان Add گره جدید به درخت خصیصه Tag را با سطر جاری دیتابیس پر کنید.

جدول دیتابیس قسمت اعظم اطلاعات آن قبلا وارد شده است. tag مربوط به آن رکوردها چه می شود؟

نقل قول
در این جستجو من با عبارت پیدا شده کاری ندارم بلکه از فیلد دیگری که واژه معادل لاتین آن است کار دارم

یعنی وقتی روی نودی کلیک می شود علاوه بر آنکه موقعیت آن را در رکوردهای تیبل پیدا می کند، در رکورد پیدا شده بتوان فیلدی غیر از فیلد فعلی را برگرداند
1399-10-11 23:48
حاجی شریفی
مؤسس سایت
 
سلام
نقل قول نوشته شده توسط: zahmah
جدول دیتابیس قسمت اعظم اطلاعات آن قبلا وارد شده است. tag مربوط به آن رکوردها چه می شود؟

خصیصه Tag که قرار نیست در دیتابیس ذخیره شود !
برنامه که بالا می آید ، مگر کنترلر TreeView خودش را پر نمیکند؟ همان لحظه که در حال خواندن و پرکردن TreeView خودش است، خصیصه Tag را هم به هر گره خودش میدهد تا سطرمعادل دیتابیس را داشته باشد.

نقل قول نوشته شده توسط: zahmah
یعنی وقتی روی نودی کلیک می شود علاوه بر آنکه موقعیت آن را در رکوردهای تیبل پیدا می کند، در رکورد پیدا شده بتوان فیلدی غیر از فیلد فعلی را برگرداند

در راه کار بالا ما تمام فیلدهای دیتابیس را زمان کلیک داریم ، مانند نمونه کدی که برای treeView1_NodeMouseClick نوشتیم

پیشنهاد میکنم یکبار دیگر پاسخ را با دقت مطالعه کنید
1399-10-13 01:29
zahmah

 
سلام
ببخشید جدول اطلاعات را طبق فرموده شما پیاده کردم. اما موفق به پیاده سازی child ها نشدم.
var Categories = Mydb.tbl_Category.ToList();
foreach (var cat in Categories)
{
if(cat.Parent_id==null)
{
var node = new TreeNode()
{
Text = cat.Name_Farsi,
Tag = cat
};
tv_Category.Nodes.Add(node);
}
else
{
//این قسمت مشکل دارم
}
}


کد پیاده ساری این جدول در treeview را هنگام لود فرم می شود بگوئید (همزمان خصیصه Tag را هم به هر گره بدهد )
فیلدهای جدولم هم اینها هستند: id و Parent_id و Name_Latin و Name_Farsi

فیلد کلید خارجی (Parent_id ) مگر در ارتباط دو جدول کاربرد ندارد؟ شما فرمودید فقط یک جدول بسازم...
1399-10-14 12:39 تعریف Entity در EF بصورت درختی
حاجی شریفی
مؤسس سایت
 
سلام
بطور معمول پردازش ها و عملیات ها روی درخت ها مثال بسیار خوبی برای توابع بازگشتی هستند
ما عمق هایی داریم که نمیدانیم تا چند سطح پیش میرود و در هر عمق هم شبیه عمیق دیگر باید کاری را انجام دهیم
نمونه کد Search به صورت بازگشتی و عمق به عمق را در مطلب قبلی برایتان قرار دادم

برای پرکردن و ساخت یک درخت هم ، بهترین راه استفاده از یک تابع بازگشتی است
خیلی علاقه مند بودم که کد این کار را برایتان قرار نمیدادم !!! تا خودتان تلاشی کنید و بیشتر و بهتر یادبگیرید ...
ولی میدانم که مشغله ادامه کار را به چند روز دیگر منتقل میکند و برای شما سخت خواهد بود
ولی باز هم پیشنهاد میکنم بدون Copy و Paste کد پایین ، با در نظر گرفتن نکته کلیدی "تابع بازگشتی" و نهایت با نگاه کردن به کد Search قبلی ...
اول خودتان تلاش کنید و کدی برای کار جاری تان بنویسید، بعد اگر نتوانستید ، نگاه و تقلبی از کد زیر داشته باشید.
https://en.wikipedia.org/wiki/Recursion_(computer_science)
https://fa.wikipedia.org/wiki/بازگشت_(علوم_رایانه)


اول کلاس Entity مربوطه را بدین شکل در Entity Framework-Code First تعریف کنید تا ارتباطات و کلید خارجی ها به درستی برقرار شود و EF در این تابع بازگشتی کمک تان کند و کدنویسی تان را کاهش دهد
using  System ;
using System.Collections.Generic ;
using System.ComponentModel.DataAnnotations ;
using System.ComponentModel.DataAnnotations.Schema ;

namespace xxx { ...

[Table( "tbl_Category" )]
public class Category
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get ; set ; }
public int ? Parent_ID { get ; set ; }
public string Name_Latin { get ; set ; }
public string Name_Farsi { get ; set ; }

[ForeignKey(nameof(Parent_ID))]
public virtual Category Parent { get ; set ; }

[InverseProperty(nameof(Parent))]
public virtual ICollection<Category> Childs { get ; set ; }
}
1399-10-14 12:46 ساخت و پرکردن بازگشتی یک درخت از دیتابیس به کمک EF
حاجی شریفی
مؤسس سایت
 
در نهایت از کدی شبیه این و آن تابع DbNestedLoad بدون آرگومان جهت بارگذاری درخت استفاده کنید.


private void  DbNestedLoad(TreeNodeCollection destin, ICollection<Category> source)
{
if (source == null || destin == null ) return ;
foreach (var dbRow in source)
{
var node = new TreeNode()
{
Text = dbRow.Name_Farsi,
Tag = dbRow
};
destin.Add(node) ;
this .DbNestedLoad(node.Nodes, dbRow.Childs) ;
}
}

public void DbNestedLoad()
{
//using (var db = new EFDbContext(...) | di.Resolve<EFDbContext>() | factory.Create() ... | ...) {
var roots = db.tbl_Category.Where(row => !row.Parent_ID.HasValue).ToList() ;
this .DbNestedLoad(this .tv_Category.Nodes, roots) ;
}

کد را امتحان نکرده ام ولی به احتمال زیاد کار کرده و مشکلی ندارد.
موفق باشید.
1399-10-22 00:43
zahmah

 
سلام
ببخشید از قسمت اول کدتان چیزی متوجه نمیشوم و اینجور کدنویسی را کار نکرده ام
1399-10-22 00:45
zahmah

 
سلام
ببخشید از قسمت اول کدتان چیزی متوجه نمیشوم و اینجور کدنویسی را کار نکرده ام(همه تیبل ها از قبل ساخته شده اند)
منظورم کد زیر است که وقتی کد مربوطه را در piblic partial قرار میدهم ارور می دهد:
[Table( "tbl_Category" )]
public class Category
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get ; set ; }
public int ? Parent_ID { get ; set ; }
public string Name_Latin { get ; set ; }
public string Name_Farsi { get ; set ; }

[ForeignKey(nameof(Parent_ID))]
public virtual Category Parent { get ; set ; }

[InverseProperty(nameof(Parent))]
public virtual ICollection<Category> Childs { get ; set ; }
}


ارور ظاهر شده :
Error 4 The type 'System.Windows.Markup.IQueryAmbient' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\PresentationFramework.dll Data_Management
1399-10-22 01:02
zahmah

 
من کد بالا را که مشکل داشت درون کد فرمم قرار ندادم و آرگومان تابع DbNestedLoad را به صورت زیر تغییر دادم که فقط نودهای ریشه را میسازد:
private void DbNestedLoad(TreeNodeCollection treeNodCollect, ICollection<tbl_CatLayer> source)
tbl_CatLayer نام جدول طبقه بندی درخت در دیتابیس است

من کلید خارجی را هیچ جا تعریف نکرده ام مشکل از آن نمیتواند باشد؟
1399-10-22 22:57
zahmah

 
ار این عبارت YOUR_ENTITY_ROW_TYPE در کد زیر چیزی متوجه نشدم:
var dbRow = (YOUR_ENTITY_ROW_TYPE)e.Node.Tag ;

آیا عبارتهای ثابت خاصی باید به جای آن بگذارم؟
1399-10-24 22:01
حاجی شریفی
مؤسس سایت
 
سلام
نقل قول نوشته شده توسط: zahmah
ببخشید از قسمت اول کدتان چیزی متوجه نمیشوم و اینجور کدنویسی را کار نکرده ام

خوب ، همانطور که در روش خودتان Relation های یک جدول را برقرار میکنید، اقدام کنید.
آیا روش اتصال خودتان به دیتابیس را بلد هستید؟
به هر شیوه ای که خودتان بلد هستید، فرزندان یک موجودیت را بارگذاری کنید !

شیوه ای که من در کد بالا استفاده کردم به نام EF-CodeFirst معروف است و جدیدترین و بروزترین شیوه ارتباط است
این روش را مایکروسافت در dotNetCore جدید هم پشتیبانی میکند که یک یا دو ماه قبل نسخه پنجم آن هم منتشر شد.


نقل قول نوشته شده توسط: zahmah
You must add a reference to assembly System.Xaml ...

بعید بنظر میرسد این خطا ارتباطی با EF داشته باشد
احتمالا یک کار خیلی نامعقولی در XAML انجام داده اید
اصلا پروژه تان WinForm است یا WPF ؟

نقل قول نوشته شده توسط: zahmah
من کلید خارجی را هیچ جا تعریف نکرده ام مشکل از آن نمیتواند باشد؟

بله مشکل دارد، بالاخره هر طور بلد هستید بچه های یک گره را بارگذاری کنید

نقل قول نوشته شده توسط: zahmah
از این عبارت YOUR_ENTITY_ROW_TYPE در کد زیر چیزی متوجه نشدم:
var dbRow = (YOUR_ENTITY_ROW_TYPE)e.Node.Tag ;
آیا عبارتهای ثابت خاصی باید به جای آن بگذارم؟

باید نام کلاس سطر دیتابیس تان را جای این قرار دهید
مثلا شاید یک سطر دیتابیس شما در سی-شارپ نام کلاسش باید PersonelRow ! یا در مثال من نام کلاس است Category
شما هر نامی که آن کلاس سطر دارد را باید جای این قرار دهید
1399-10-25 00:18
zahmah

 
سلام
متاسفانه در سی شارپ مبتدی هستم و خیلی به جنبه های مختلف سی شارپ احاطه ندارم و توضیحات کامل شما را متوجه نمیشوم. ببخشید.
1399-10-25 18:40
zahmah

 
سلام
متاسفانه در سی شارپ مبتدی هستم و خیلی به جنبه های مختلف سی شارپ احاطه ندارم و توضیحات کامل شما را متوجه نمیشوم. ببخشید.