PDA

View Full Version : سوال: چگونه با entityFramework اطلاعاتی که به صورت master/detial هستند را ذخیره کنیم؟



sayanpro
سه شنبه 21 آذر 1396, 19:10 عصر
سلام دوستان گرامی
فرض کنید یک جدول A داریم که فیلد ID آن به صورت Identity اضافه می شود. این فیلد در جدول B به صورت FK استفاده شده است. می خواهیم به صورت همزمان اطلاعات جدول A,B را با هم به روش entityFramework ذخیره کنیم. راه حل پیشنهادی شما جهت درج این گونه اطلاعات چیست؟

با تشکر.

parvizwpf
سه شنبه 21 آذر 1396, 19:40 عصر
یک نمونه کد:
using (var dataRepository = this.dataRepositoryFactory.Create())
{
if (Mode == "New")
{
Order newOrder = new Order();

// This doesn't make sense. Either generate a random order number (e.g. a Guid), or just use the Order.Id as an order number, although I don't recommend it.
int maxOrderNumber = dataRepository.Orders.Select(o => o.OrderNumber).DefaultIfEmpty(0).Max();
maxOrderNumber++;

newOrder.OrderNumber = maxOrderNumber;
newOrder.Date = DateTime.ParseExact(txtOrderDate.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
newOrder.CustomerID = Convert.ToInt32(ddlCustomer.SelectedValue);
newOrder.Status = 1;

dataRepository.Orders.Add(newOrder);

foreach (DataRow dt in dtOrderDetails.Rows)
{
OrderDetails newOrderDetails = new OrderDetails();
newOrderDetails.OrderNumer = maxOrderNumber;
newOrderDetails.ProductId = Convert.ToInt32(dt["ProductId"]);
newOrderDetails.Quantity = Convert.ToInt32(dt["Quantity"]);

newOrder.OrderDetails.Add(newOrderDetails);
}

myOrder = newOrder;
}

if (Mode == "Edit")
{
Order editedOrder = dataRepository.Orders.FirstOrDefault(o => o.Id == myOrder.Id);

editedOrder.Date = DateTime.ParseExact(txtOrderDate.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
editedOrder.CustomerID = Convert.ToInt32(ddlCustomer.SelectedValue);
editedOrder.OrderDetails.Clear();

foreach (DataRow dt in dtOrderDetails.Rows)
{
OrderDetails editedOrderDetails = new OrderDetails();
editedOrderDetails.OrderNumer = editedOrder.OrderNumber;
editedOrderDetails.ProductId = Convert.ToInt32(dt["ProductId"]);
editedOrderDetails.Quantity = Convert.ToInt32(dt["Quantity"]);

editedOrder.OrderDetails.Add(editedOrderDetails);
}
}

dataRepository.Save();
}

sayanpro
چهارشنبه 22 آذر 1396, 00:45 صبح
مشکل من اینه که ID اولم Identity داره و یعنی خود sql برای هر رکورد که اضافه میشه خودش یکی اضافه میکنه، ولی توی مثال شما، newOrder.OrderNumber = maxOrderNumber; خودتان دستی تنظیم کرده اید.
من میخوام saveChanges() همزمان برای 2 جدولم باهم رخ بده.


یک نمونه کد:
using (var dataRepository = this.dataRepositoryFactory.Create())
{
if (Mode == "New")
{
Order newOrder = new Order();

// This doesn't make sense. Either generate a random order number (e.g. a Guid), or just use the Order.Id as an order number, although I don't recommend it.
int maxOrderNumber = dataRepository.Orders.Select(o => o.OrderNumber).DefaultIfEmpty(0).Max();
maxOrderNumber++;

newOrder.OrderNumber = maxOrderNumber;
newOrder.Date = DateTime.ParseExact(txtOrderDate.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
newOrder.CustomerID = Convert.ToInt32(ddlCustomer.SelectedValue);
newOrder.Status = 1;

dataRepository.Orders.Add(newOrder);

foreach (DataRow dt in dtOrderDetails.Rows)
{
OrderDetails newOrderDetails = new OrderDetails();
newOrderDetails.OrderNumer = maxOrderNumber;
newOrderDetails.ProductId = Convert.ToInt32(dt["ProductId"]);
newOrderDetails.Quantity = Convert.ToInt32(dt["Quantity"]);

newOrder.OrderDetails.Add(newOrderDetails);
}

myOrder = newOrder;
}

if (Mode == "Edit")
{
Order editedOrder = dataRepository.Orders.FirstOrDefault(o => o.Id == myOrder.Id);

editedOrder.Date = DateTime.ParseExact(txtOrderDate.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
editedOrder.CustomerID = Convert.ToInt32(ddlCustomer.SelectedValue);
editedOrder.OrderDetails.Clear();

foreach (DataRow dt in dtOrderDetails.Rows)
{
OrderDetails editedOrderDetails = new OrderDetails();
editedOrderDetails.OrderNumer = editedOrder.OrderNumber;
editedOrderDetails.ProductId = Convert.ToInt32(dt["ProductId"]);
editedOrderDetails.Quantity = Convert.ToInt32(dt["Quantity"]);

editedOrder.OrderDetails.Add(editedOrderDetails);
}
}

dataRepository.Save();
}

parvizwpf
چهارشنبه 22 آذر 1396, 08:28 صبح
اگر در دیتابیس identity ست شده باشه نیازی نیست شما در کد آی دی ست کنید. چه برای مستر چه برای دیتیل

sayanpro
جمعه 24 آذر 1396, 22:09 عصر
خب اگر ID جدول Master به Detial ندم، چطوری میتونه بفهمه و اطلاعات ثبت کنه، این طوری که ارور میده، اگه میتونید لطفا یک مثال ساده بزنید.
ممنونم.


اگر در دیتابیس identity ست شده باشه نیازی نیست شما در کد آی دی ست کنید. چه برای مستر چه برای دیتیل

ali_md110
شنبه 25 آذر 1396, 02:39 صبح
این روش اتمیک نیست و جامعیت برنامه حفظ نمیشه بهتره برای درج داده های مرتبط از الگوی Unitofwork استفاده کنید
ولی در همین روش شما
بعد این قسمت



dataRepository.Orders.Add(newOrder);

دستور savechange() بدید و بلافاصله ef کلید اصلی را به برنامه برگشت میدهد
newOrder.Id میشه کلیدی که نیاز دارید
و از کلید اصلی در جدول دیتیل استفاده کنید

parvizwpf
شنبه 25 آذر 1396, 14:02 عصر
با تشکر از حسن توجه دوستمون

محمد آشتیانی
سه شنبه 28 آذر 1396, 11:26 صبح
سلام
اصلا چه نیازی هست که SaveChanges صدا زده بشه و آیدی رو بگیریم؟ این موردی هست که خود EF مدیریت میکنه و انجامش میده

فرض بفرمائید یک کلاس پست داریم و یک کلاس کامنت (به شرح ذیل) و اینها یک ارتباط یک به چند دارند (هر پست میتونه صفر یا بیشتر کامنت داشته باشه)

public class Post {
public Post()
{
this.Comments = new List<Comment>();
}


public int PostId { get; set; }
public string Title { get; set; }
public int? AuthorId { get; set; }
public DateTime? PublishDateTime { get; set; }
public string PostContent { get; set; }
public string Description { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}


public class Comment {
public int CommentId { get; set; }
public int? PostId { get; set; }
public int? Sequence { get; set; }
public int? UserId { get; set; }
public DateTime? SubmitDateTime { get; set; }
public string CommentText { get; set; }
public virtual Post Post { get; set; }
}

با این تعریف ها ، کد زیر یک رکورد در جدول Post درج میکنه و تعداد 5 رکورد در جدول Comment درج میکنه که FK اونها ، همون مقدار ID رکورد جدول Post هست
var ctx = new SampleDBContext();

var post = new Post
{
Title = "Test Title",
PublishDateTime = DateTime.Now,
PostContent = "Lorem ipsum dolor",
Description = "...",


Comments = new List<Comment>
{
new Comment { CommentText = "First" },
new Comment { CommentText = "Second" },
new Comment { CommentText = "Third" },
new Comment { CommentText = "Fourth" },
new Comment { CommentText = "Fifth" },
}
};


ctx.Posts.Add(post);
ctx.SaveChanges();

البته این کد رو میشه شکل های دیگری هم نوشت ، اما ساده ترینش به نظر بنده اینجوری میشه.

parvizwpf
سه شنبه 28 آذر 1396, 11:34 صبح
با تشکر از شما. در بالا توضیح داده بودم که نیازی نیست