PDA

View Full Version : سوال: دستوری برای درج چند رکورد به صورت یکجا در entity framework؟



karimi.ali2005
شنبه 04 خرداد 1392, 21:48 عصر
در sql وقتی خواسته باشیم یک select را به صورت یکجا به جدول اضافه کنیم می توانیم از دستور insert into به همراه select استفاده کنیم و چندین رکورد را به صورت یکجا به جدول اضافه کنیم
من داخل entity frame work یک foreach نوشتم و یکی یکی به جدول اضافه کردم اما خیلی وقت گیر هست مثلا یک insert چهار هزار رکوردی که شاید 1 ثانیه بیشتر در sql طول نمیکشه تا به یک جدول اضافه بشه حدود 4 الی 5 دقیقه برای 4 هزار رکورد در entity framework طول میکشه آیا راه حلی هست ؟
با تشکر

mo.esmp
یک شنبه 05 خرداد 1392, 02:58 صبح
این کار فعلن تو EF عملی نیست ولی من یه راه بهت میگم خیلی راحت و بدون نوشتن یه خط کوئری SQL این کار رو انجام بدی.
اول از همه کتابخانه EntityDataReader (https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs) رو به پروژەت ازافه کن.
فرز میکنیم یه Entity داری با نام Customer یه لیست از این Customer (منزورم List<Customer>s هست) با نام customerList داری کی میخوای وارد دیتابیس کنی و فرز میکنیم نام جدول مربوته Customer در دیتابیس dbo.Customer هست و نام connectionStringمون هم مسلن تو web.config زخیره شده است، DataConnection هست.
var connectionString = ConfigurationManager.ConnectionStrings["DataConnection"].ConnectionString;
var bulkCopy = new SqlBulkCopy(connectionString) { DestinationTableName = "dbo.Customer" };
bulkCopy.WriteToServer(customerList.AsDataReader() );
به همین راحتی!

karimi.ali2005
یک شنبه 05 خرداد 1392, 07:06 صبح
این کار فعلن تو EF عملی نیست ولی من یه راه بهت میگم خیلی راحت و بدون نوشتن یه خط کوئری SQL این کار رو انجام بدی.
اول از همه کتابخانه EntityDataReader (https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs) رو به پروژەت ازافه کن.
فرز میکنیم یه Entity داری با نام Customer یه لیست از این Customer (منزورم List<Customer>s هست) با نام customerList داری کی میخوای وارد دیتابیس کنی و فرز میکنیم نام جدول مربوته Customer در دیتابیس dbo.Customer هست و نام connectionStringمون هم مسلن تو web.config زخیره شده است، DataConnection هست.
var connectionString = ConfigurationManager.ConnectionStrings["DataConnection"].ConnectionString;
var bulkCopy = new SqlBulkCopy(connectionString) { DestinationTableName = "dbo.Customer" };
bulkCopy.WriteToServer(customerList.AsDataReader() );
به همین راحتی!
سرعت این چند خط کد مثل sql هست و این کلاس جز مجموعه .net هست یا باید دانلود کنم

Mahmoud.Afrad
یک شنبه 05 خرداد 1392, 12:08 عصر
کد خودتون رو همراه ساختار دو جدول قرار بدید تا تست کنیم.

mo.esmp
یک شنبه 05 خرداد 1392, 20:20 عصر
برای اطلاعات بیشتر درج یک باره چندین رکورد بصورت همزمان هنگام استفاده از ORMها (http://www.dotnettips.info/post/1334/%D8%AF%D8%B1%D8%AC-%DB%8C%DA%A9-%D8%A8%D8%A7%D8%B1%D9%87-%DA%86%D9%86%D8%AF%DB%8C%D9%86-%D8%B1%DA%A9%D9%88%D8%B1%D8%AF-%D8%A8%D8%B5%D9%88%D8%B1%D8%AA-%D9%87%D9%85%D8%B2%D9%85%D8%A7%D9%86-%D9%87%D9%86%DA%AF%D8%A7%D9%85-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-orm%D9%87%D8%A7) رو مطالعه کنید.

karimi.ali2005
دوشنبه 06 خرداد 1392, 07:25 صبح
برای اطلاعات بیشتر درج یک باره چندین رکورد بصورت همزمان هنگام استفاده از ORMها (http://www.dotnettips.info/post/1334/%D8%AF%D8%B1%D8%AC-%DB%8C%DA%A9-%D8%A8%D8%A7%D8%B1%D9%87-%DA%86%D9%86%D8%AF%DB%8C%D9%86-%D8%B1%DA%A9%D9%88%D8%B1%D8%AF-%D8%A8%D8%B5%D9%88%D8%B1%D8%AA-%D9%87%D9%85%D8%B2%D9%85%D8%A7%D9%86-%D9%87%D9%86%DA%AF%D8%A7%D9%85-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-orm%D9%87%D8%A7) رو مطالعه کنید.
برای حذف و update به صورت یکجا در این لینکی که گذاشتید یک کلاس معرفی کرده کسی با این کلاس کار کرده؟
یا اصلا مثل همین روش که اضافه کردن چندین رکورد به database را فراهم می کنه روشی برای حذف و ویرایش هم وجود دارد؟

Mahmoud.Afrad
دوشنبه 06 خرداد 1392, 11:38 صبح
نمیدونم کد شما به چه صورته ولی من 4000 رکورد رو در 1 ثانیه سلکت و در جدول دیگه درج کردم.

mo.esmp
دوشنبه 06 خرداد 1392, 12:38 عصر
برای حذف و update به صورت یکجا در این لینکی که گذاشتید یک کلاس معرفی کرده کسی با این کلاس کار کرده؟
یا اصلا مثل همین روش که اضافه کردن چندین رکورد به database را فراهم می کنه روشی برای حذف و ویرایش هم وجود دارد؟

من با کتابخانه Entity Framework Extended Library کار کردم و به خوبی کار میکنه. امتحانش زرری نداره کافیه از تریق nuget نسبش و تستش کنید.

karimi.ali2005
سه شنبه 07 خرداد 1392, 07:07 صبح
نمیدونم کد شما به چه صورته ولی من 4000 رکورد رو در 1 ثانیه سلکت و در جدول دیگه درج کردم.
گفتم چه روشی



من داخل entity frame work یک foreach نوشتم و یکی یکی به جدول اضافه کردم اما خیلی وقت گیر هست مثلا یک insert چهار هزار رکوردی که شاید 1 ثانیه بیشتر در sql طول نمیکشه تا به یک جدول اضافه بشه حدود 4 الی 5 دقیقه برای 4 هزار رکورد در entity framework طول میکشه آیا راه حلی هست ؟
با تشکر
شما هم از روش mo.esmp (http://barnamenevis.org/member.php?24893-mo.esmp) استفاده کردید?
میشه بگید چکار کردید؟

karimi.ali2005
سه شنبه 07 خرداد 1392, 07:56 صبح
من با کتابخانه Entity Framework Extended Library کار کردم و به خوبی کار میکنه. امتحانش زرری نداره کافیه از تریق nuget نسبش و تستش کنید.
نمونه مثالی دارید یا سایتی که مثال داشته باشه؟

mo.esmp
سه شنبه 07 خرداد 1392, 13:19 عصر
نمونه مثالی دارید یا سایتی که مثال داشته باشه؟

مسال در مورد EntityDataReader یا Entity Framework Extended Library ؟

karimi.ali2005
چهارشنبه 08 خرداد 1392, 06:48 صبح
مسال در مورد EntityDataReader یا Entity Framework Extended Library ؟
بله اگه امکان داره
یک مثال بزارید
منظورم یک قطعه source کوچیک

karimi.ali2005
دوشنبه 20 خرداد 1392, 22:24 عصر
من برای ویرایش چند رکورد به صورت یکجا از Entity Framework Extended Library استفاده کردم
اما مشکلی دارم این است من یک جدول در پایگاه دارم که می خوام به صورت یکجا ویرایش کنم به این صورت که ابتدا شماره فیلد هایی که را قرار است تغییر دهم(فیلد ID) داخل یک لیست ریختم و سپس از جدول فقط اون فیلدها رو ویرایش کنم
چند روش برای join جدول با این لیست امتحان کردم یا join خطا می دهد اگر join نیز مشکلی نداشت مقدار برگشتی از نوع enumerable هست و زمانی که از update کلاس Entity Framework Extended Libraryاستفاده میکنم
خطا می دهد که لیستی که قرار است update شود باید از نوع dbquery باشد

Mahmoud.Afrad
دوشنبه 20 خرداد 1392, 23:55 عصر
طبق ef جواب میدم.
نیاز به join نیست.
ابتدا لیست idهایی که باید ویرایش شوند رو ایجاد میکنید. کافیه رکوردهایی از جدول رو پیدا کنید که id اون رکوردها در لیست موجود باشه. این کار رو از طریق متد Contains لیست انجام دهید.
مثال زیر میاد مشخصه Name رکوردهایی که idزوج دارند رو تغییر میده.(ids لیست id ها)

List<int> ids = db.tbl.Where(i => i.id % 2 == 0).Select(i=> i.id).ToList();

var q = db.tbl.Where(item => ids.Contains(item.id));
q.ToList().ForEach(i => i.name = "updated");
db.SaveChanges();

karimi.ali2005
سه شنبه 21 خرداد 1392, 07:10 صبح
طبق ef جواب میدم.
نیاز به join نیست.
ابتدا لیست idهایی که باید ویرایش شوند رو ایجاد میکنید. کافیه رکوردهایی از جدول رو پیدا کنید که id اون رکوردها در لیست موجود باشه. این کار رو از طریق متد Contains لیست انجام دهید.
مثال زیر میاد مشخصه Name رکوردهایی که idزوج دارند رو تغییر میده.(ids لیست id ها)

List<int> ids = db.tbl.Where(i => i.id % 2 == 0).Select(i=> i.id).ToList();

var q = db.tbl.Where(item => ids.Contains(item.id));
q.ToList().ForEach(i => i.name = "updated");
db.SaveChanges();


اگر تعداد فیلدهای که قرار است برا اساس انها فیلتر شود دوتا یا بیشتر باشه چکار می کنیم مثلا اگر لیست ما یک کلاس باشه(به جای int) که چند ستون داشته باشه و فیلتر ما بر اساس دو ستون از این لیست باشه چکار میکنیم

karimi.ali2005
سه شنبه 21 خرداد 1392, 09:51 صبح
سورس یک مثال کوچیک به همراه پایگاه در استفاده از کلاس Entity Framework Extended Library
خطا:Unable to create a constant value of type 'extendeexample.MyClass'. Only primitive types or enumeration types are supported in this context.
http://www.saghlayn.ir/karimi/project.rar

Mahmoud.Afrad
سه شنبه 21 خرداد 1392, 17:44 عصر
باز هم فرقی نمیکنه. چون در جدول t1 یک ستون کلید اصلی هست پس کافیه براساس همین کلید اصلی(id) فیلتر رو انجام بدید.(اگر کلید اصلی چند ستونه بود سوال شما صحیح بود)

List<MyClass> query = new List<MyClass>()
{
new MyClass() {ID = 1, testid = 4},
new MyClass() {ID = 2, testid = 2},
new MyClass() {ID = 3, testid = 2},
new MyClass() {ID = 4, testid = 1},
new MyClass() {ID = 5, testid = 6}
};

using (mytestEntities db = new mytestEntities())
{
var ids = query.Select(i => i.ID);

var QuestionPeriodAnswerUpdate = from t in db.t1
where ids.Contains(t.ID) && t.checks == true
select t;

using (var tx = db.BeginTransaction())
{
try
{
QuestionPeriodAnswerUpdate.ToList().ForEach(item => item.checks = false);
tx.Commit();
db.SaveChanges();
}
catch (Exception)
{
tx.Rollback();
}
}
}

karimi.ali2005
چهارشنبه 22 خرداد 1392, 06:48 صبح
باز هم فرقی نمیکنه. چون در جدول t1 یک ستون کلید اصلی هست پس کافیه براساس همین کلید اصلی(id) فیلتر رو انجام بدید.(اگر کلید اصلی چند ستونه بود سوال شما صحیح بود)

List<MyClass> query = new List<MyClass>()
{
new MyClass() {ID = 1, testid = 4},
new MyClass() {ID = 2, testid = 2},
new MyClass() {ID = 3, testid = 2},
new MyClass() {ID = 4, testid = 1},
new MyClass() {ID = 5, testid = 6}
};

using (mytestEntities db = new mytestEntities())
{
var ids = query.Select(i => i.ID);

var QuestionPeriodAnswerUpdate = from t in db.t1
where ids.Contains(t.ID) && t.checks == true
select t;

using (var tx = db.BeginTransaction())
{
try
{
QuestionPeriodAnswerUpdate.ToList().ForEach(item => item.checks = false);
tx.Commit();
db.SaveChanges();
}
catch (Exception)
{
tx.Rollback();
}
}
}

اگر در مثال دیده باشید تعداد ستون هایی که قرار است برا اساس اون فیلتر شود ID و testid شو هست


گر تعداد فیلدهای که قرار است برا اساس انها فیلتر شود دوتا یا بیشتر باشه چکار می کنیم

Mahmoud.Afrad
چهارشنبه 22 خرداد 1392, 19:33 عصر
سوالتون اشتباهه.
از بین id , testid یکیشون یعنی id کلید اصلی هست. خب از اونجایی که id برای چند رکورد نمیتونه تکراری باشه پس با داشتن id نیازی به testid نیست. یعنی هیچ دو رکوردی نیستند که id یکسان و testid متفاوتی داشته باشند. پس عملا testid در فیلتر نقشی نداره.
وقتی شما لیست MyClass رو دارید پس در اصل لیست id های لازم رو دارید. کافیه از جدول رکوردهایی رو بیرون بکشید که idشون در لیست idها باشه.


اگر تعداد فیلدهای که قرار است برا اساس انها فیلتر شود دوتا یا بیشتر باشه چکار می کنیمسوال شما وقتی درسته که id , testid با هم کلید باشند یا هیچکدام کلید نباشند.

karimi.ali2005
چهارشنبه 22 خرداد 1392, 21:30 عصر
سوالتون اشتباهه.
از بین id , testid یکیشون یعنی id کلید اصلی هست. خب از اونجایی که id برای چند رکورد نمیتونه تکراری باشه پس با داشتن id نیازی به testid نیست. یعنی هیچ دو رکوردی نیستند که id یکسان و testid متفاوتی داشته باشند. پس عملا testid در فیلتر نقشی نداره.
وقتی شما لیست MyClass رو دارید پس در اصل لیست id های لازم رو دارید. کافیه از جدول رکوردهایی رو بیرون بکشید که idشون در لیست idها باشه.

سوال شما وقتی درسته که id , testid با هم کلید باشند یا هیچکدام کلید نباشند.

یک جورایی id و testid با هم کلید هستند
من یک gridview دارم که حاصل join چند جدول است که دو تا از فیلدهای ان برای من مهم هست id و testid(برای اینکه مثال کوچیک باشه اینجا MyClass را فقط با دو فیلد تعریف کردم)
چون gridview من حاصل چند join هست و خروجی select را داخل myclass ریختم به راحتی می توانم داخل gridview تغییراتی ایجاد کنم و چون select من join دارد تغییرات در حافظه اصلی ذخیره شد به محض اینکه کاربر که ذخیره رو زد من می خواهم تنها id هایی رو ویرایش کند که testid آنها تغییر کرده باشد کافی هست د وتا جدول myclass و جدول t1 با هم join شوند و به شرط اینکه id ها یکسان و tesid ها نامساوی باشند دستور select و ویرایش این چیست؟

وسوال دوم اینکه
البته من به کدی هم د ر جای دیگر برنامه ام نیاز دارم که بر اساس دو ستون فیلتر کنه مثلا فرض کنیم id و testid با هم کلید هستند دستور join به جه شکل می شود؟

Mahmoud.Afrad
چهارشنبه 22 خرداد 1392, 22:27 عصر
میتونی با any این کارو انجام بدی. :

using (mytestEntities db = new mytestEntities())
{
var QuestionPeriodAnswerUpdate = from t in db.t1
where query.Any(item => item.ID == t.ID && item.testid == t.testid)
&& t.checks == true
select t;

using (var tx = db.BeginTransaction())
{
try
{
QuestionPeriodAnswerUpdate.ToList().ForEach(item => item.checks = false);
tx.Commit();
db.SaveChanges();
}
catch (Exception)
{
tx.Rollback();
}
}
}

karimi.ali2005
پنج شنبه 23 خرداد 1392, 11:09 صبح
میتونی با any این کارو انجام بدی. :

using (mytestEntities db = new mytestEntities())
{
var QuestionPeriodAnswerUpdate = from t in db.t1
where query.Any(item => item.ID == t.ID && item.testid == t.testid)
&& t.checks == true
select t;

using (var tx = db.BeginTransaction())
{
try
{
QuestionPeriodAnswerUpdate.ToList().ForEach(item => item.checks = false);
tx.Commit();
db.SaveChanges();
}
catch (Exception)
{
tx.Rollback();
}
}
}

تا حالا دستور join اولی را امتحان کردی یعنی join بین لیست وجدول خطای زیر را می دهد

Unable to create a constant value of type 'extendeexample.MyClass'. Only primitive types or enumeration types are supported in this context.

Mahmoud.Afrad
پنج شنبه 23 خرداد 1392, 17:59 عصر
تا حالا دستور join اولی را امتحان کردی یعنی join بین لیست وجدول خطای زیر را می دهد

Unable to create a constant value of type 'extendeexample.MyClass'. Only primitive types or enumeration types are supported in this context.
نه وقتی نیازی نیست برای چی join بزنی. کوئری بالا مگه جواب نداد؟ در کوئری بالا براساس id , testid چک میشه اگر اون رکورد در لیستquery بود و checks اون رکورد true بود اون رکورد رو انتخاب میکنه. مگه همینو نمیخواستی؟

خطا هم میگه اون دو نوع شمارشی که میخوای join کنی باید در context موجود باشند که MyClass در context نیست.

اگر یه توضیحی بدی که MyClass رو برای چی ایجاد کردی و اصلا آپدیت بر چه رکوردهایی اعمال میشه. بهتر میشه راهنمایی کرد. اینکه آیا اطلاعات در کنترلی نمایش داده میشن یا نه؟ و کلا اینکه میخوای چه کار کنی؟

karimi.ali2005
شنبه 25 خرداد 1392, 07:33 صبح
نه وقتی نیازی نیست برای چی join بزنی. کوئری بالا مگه جواب نداد؟

نه دیگه گفتم همون خطا را داد اگه نشه بین یک لیست و یک جدول join زد چه زبان یکپارچه ای هست درست کردند


اگر یه توضیحی بدی که MyClass رو برای چی ایجاد کردی و اصلا آپدیت بر چه رکوردهایی اعمال میشه. بهتر میشه راهنمایی کرد. اینکه آیا اطلاعات در کنترلی نمایش داده میشن یا نه؟ و کلا اینکه میخوای چه کار کنی؟

قبلا گفتم برای چی میخوام


من یک gridview دارم که حاصل join چند جدول است که دو تا از فیلدهای ان برای من مهم هست id و testid(برای اینکه مثال کوچیک باشه اینجا MyClass را فقط با دو فیلد تعریف کردم)
چون gridview من حاصل چند join هست و خروجی select را داخل myclass ریختم به راحتی می توانم داخل gridview تغییراتی ایجاد کنم و چون select من join دارد تغییرات در حافظه اصلی ذخیره شد به محض اینکه کاربر که ذخیره رو زد من می خواهم تنها id هایی رو ویرایش کند که testid آنها تغییر کرده باشد کافی هست د وتا جدول myclass و جدول t1 با هم join شوند و به شرط اینکه id ها یکسان و tesid ها نامساوی باشند دستور select و ویرایش این چیست؟