پروژه : نرم افزار ثبت اطلاعات مشتریان با دیتابیس SQL Server و سی شارپ WPF با ویژوال استدیو 2019
موضوع چیه : توی دریافت اطلاعات از دیتابیس من به دلیل مشکلات فنی برای یک پروژه خاص نمیخوام از Entity Framework استفاده کنم , به جای اون میخوام از روش ADO.Net با استفاده مستقیم از کویری های خام SQL Server اطلاعات رو از دیتابیس واکشی کنم مثال : SELECT * FROM CUSTOMERS
مشکل چیه ؟ : توی انتیتی فریمورک باتوجه به مدلی که از روی دیتابیس میسازه (توی روش DB First) ما میتونیم کویری های SQL رو مستقیما به این شکل استفاده کنیم :
//MyModel base Table :
public partial class CUSTOMERS
{
public int ID{ get; set; }
public string NAME{ get; set; }
public bool Activation{ get; set; }
}
//Raw Query
var ResultData = dbContext.Database.SqlQuery<CUSTOMERS>(SELECT * FROM CUSTOMERS).ToList();
اما ما نمیتونیم با دستور مستقیم اس کوی ال به راحتی یک ستون مشخص رو سلکت کنیم چون با مدل ساخته شده همخوانی نداره :
// این دستور خطا incompatible Data رو میده
var ResultData = dbContext.Database.SqlQuery<CUSTOMERS>(SELECT NAME FROM CUSTOMERS).ToList();
اگر میخوایم این مشکل حل بشه باید مدلش رو خودمون جداگانه بسازیم :
public partial class Customized_CUSTOMERS_Model
{
public string NAME{ get; set; }
}
var ResultData = dbContext.Database.SqlQuery<Customized_CUSTOMERS_Model>(SELECT NAME FROM CUSTOMERS).ToList();
حالا چون این کار زمان بره , و کویری های مختلفی دارم و به هیچ عنوان نمیخوام به دلیل Performance نا مناسب از طرف LINQ (در هر صورت دستورات خود SQL سرعت بالاتری داره) میخوام از روش ADO.NET استفاده کنم .
چیزی که دیدم اینه که توی DataTable خودش باتوجه به کویری که زدید و نتیجه ای که داره میاد Column و Row و حتی نوع داده ها رو مشخص و مدیریت میکنه که میشه اون رو راحت توی DataGrid نمایش داد به شکل زیر :
string connectionString = "Data Source = YOUR_SERVER_NAME; Initial Catalog = YOUR_DATABASE_NAME; Integrated Security = True;";
SqlConnection con = new SqlConnection(connectionString);
con.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM CUSTOMERS ", con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
sda.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
MyDataGrid1.ItemsSource = ds.Tables[0].DefaultView;
}
con.Close();
من چه چیزی نیاز دارم ؟ :
من توی کد بالا میتونم اون رو توی دیتا گرید استفاده کنم ولی نیاز دارم که اون رو به یک لیست تبدیل کنم تا بتونم راحت مثل یک مدل در انتیتی به آیتم هاش دسترسی داشته باشم
راستش بلد نیستم به شکلی که میخوام به آیتم هاش دسترسی داشته باشم یعنی شما توی انتیتی میاین همه دیتا ها رو انتخاب میکنید یا یه ستون مشخص از یک کویری ! , من میخوام این کار رو با دیتا تیبل انجام بدم (کد دسترسی به سطر و ستون های DataTable)
محتوای ds.Tables[0].DefaultView :
در نتیجه : دوتا کار میتونم بکنم
1- دسترسی به محتوای DataTable
2- تبدیل DataTable > ToList
برای مرود اول نتونستم کاری کنم
ولی برای مورد دوم : اومدم به این شکل کار کردم :
//روش اول با استفاده از دیتا رو
List<DataRow> list123 = ds.Tables[0].DefaultView.ToTable().AsEnumerable().ToList();
//تبدیل به لیست منتها فقط انتخاب یک ستون
var empList = ds.Tables[0].AsEnumerable().Select(dataRow => new { Name = dataRow.Field<string>("NAM") }).ToList();
در نهایت به توجه به چیزی هایی که توضیح دادم چطور به آیتم های داخل DataTable دسترسی داشته باشم به صورتی که بتونم بگم : توی دیتا تیبل اگر در ستون کد مشتری مقدار کد برابر با 12 بود نام اون مشتری رو تغییر بده
یعنی استفاده از دیتا تیبل به صورتی که انگاه یک مدل (Entity) ساخته شده تا دیگه نیایم مدلی برای اون بسازیم یا ستون مشخص بهش بدیم
پ.ن : یک چیزه دیگه ای که یادم اومد اینه که آیا میشه کلاسی انعطاف پذیر توی سی شارپ ساخت که لازم نباشه حتما نتیجه کویری با پراپرتی (ستون های مدل) یکسان نباشه یعنی هرکدومش که لازمه پر بشه بقیه خالی باشه و من بتونم ستونی مشخص در کویری باتوجه به مدل انتخاب کنم ! اگر این حل بشه نیازی به این کار هایی که کردم نیست !
لینک مرتبط با این موضوع :
How to Select All row and column from Data Set to List in C# WPF
لطفا راهنمایی بفرمایید باتشکر
سلام دوست گرامی
مشکلی که فرمودید قابل حله و نیاز نیست شما از DataTable استفاده کنید. درسته که شما در کوئری خودتون
SELECT * FROM CUSTOMERS
رو نوشتید ولی تا وقتی که کوئری رو واکشی نکنید هیچ باری روی سیستم و حافظه شما قرار نمیگیره. کافیه شما قبل از قرار دادن عبارت ToList ستون های مورد نیاز خودتون رو با کمک گرفتن از Linq انتخاب کنید. به مثال زیر توجه کنید.
var ResultData = (from q in dbContext.Database.SqlQuery<CUSTOMERS>(SELECT * FROM CUSTOMERS) select new {q.Name}).ToList()
در مثال فوق اگرچه ما در رشته اس کیو ال کل ستونها رو سلکت کردیم ولی در نهایت قبل از ToList کردن دستور واکشی فقط یک ستون رو دادیم. دقیقا مشابه دستور زیر در اس کیو ال
SELECT Name FROM CUSTOMERS
در نتیجه مشکل شما حل میشه.
برای استفاده از کوئری های پیچیده و inner join از روش زیر استفاده کنید.
string constring = dbContext.Database.Connection.ConnectionString;
string query = @"SELECT Name FROM CUSTOMERS
INNER JOIN table2 ON CUSTOMERS.Name = table2.Name";
List<CUSTOMERS> customers = new List<CUSTOMERS>();
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
cmd.CommandType = CommandType.Text;
con.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
customers.Add(new CUSTOMERS
{
customerID = Convert.ToInt32(sdr["customerID"]),
Name = sdr["Name"].ToString()
});
}
}
con.Close();
}
}
جهت استفاده از کد فوق باید از کتابخانه ;using System.Data.SqlClien استفاده کنید.
تاریخ :
1401/02/24
- ساعت :
02:17:00 PM
- بازدید :
2008
- پاسخ :
1
|
تاریخ :
1402/07/23
- ساعت :
04:01:00 PM
- بازدید :
1033
- پاسخ :
1
|
تاریخ :
1402/09/08
- ساعت :
07:34:00 PM
- بازدید :
1160
- پاسخ :
1
|
تاریخ :
1402/09/21
- ساعت :
11:10:00 PM
- بازدید :
597
- پاسخ :
1
|
تاریخ :
1403/07/13
- ساعت :
12:06:00 PM
- بازدید :
349
- پاسخ :
1
|
تاریخ :
1403/06/24
- ساعت :
08:52:00 PM
- بازدید :
318
- پاسخ :
1
|
تاریخ :
1398/09/14
- ساعت :
01:58:00 PM
- بازدید :
4268
- پاسخ :
1
|
تاریخ :
1398/09/16
- ساعت :
11:41:00 AM
- بازدید :
4282
- پاسخ :
1
|
تاریخ :
1398/09/07
- ساعت :
02:15:00 PM
- بازدید :
3875
- پاسخ :
5
|
تاریخ :
1403/05/16
- ساعت :
05:43:00 AM
- بازدید :
660
- پاسخ :
0
|
تاریخ :
1401/02/24
- ساعت :
02:17:00 PM
- بازدید :
2008
- پاسخ :
1
|
تاریخ :
1403/08/29
- ساعت :
07:15:00 PM
- بازدید :
75
- پاسخ :
0
|
تاریخ :
1403/08/18
- ساعت :
10:40:00 AM
- بازدید :
109
- پاسخ :
0
|
تاریخ :
1402/07/23
- ساعت :
04:01:00 PM
- بازدید :
1033
- پاسخ :
1
|
تاریخ :
1403/05/30
- ساعت :
09:22:00 AM
- بازدید :
428
- پاسخ :
1
|
تاریخ :
1402/08/01
- ساعت :
06:25:00 PM
- بازدید :
930
- پاسخ :
1
|
تاریخ :
1402/08/16
- ساعت :
10:38:00 AM
- بازدید :
1356
- پاسخ :
1
|
تاریخ :
1398/08/17
- ساعت :
01:27:00 AM
- بازدید :
4797
- پاسخ :
1
|
تاریخ :
1402/09/08
- ساعت :
07:34:00 PM
- بازدید :
1160
- پاسخ :
1
|
تاریخ :
1402/09/21
- ساعت :
11:10:00 PM
- بازدید :
597
- پاسخ :
1
|