Entity Framework - parent child table update in single transation - c#

I am working on application where I have a parent child relation between User and Orders tables. Below are the table structures:
User:
Column | DataType | Constraint
--------|-----------|-------------
UserId | int | Primary key
Username| varchar |
Email | varchar |
IsActive| bit |
Order:
Column | DataType | Constraint
--------|-----------|----------
OrderId | int | Primary key
UserId | int | Foreign key to User.UserId
Type | smallint |
Quantity| smallint |
As per the functionality I have to update User and his orders in one go where orders can be dynamically added, removed or updated.
I am using Entity Framework 6.0 and I cannot find any best solution to update parent table (user) and child table (order) in single transaction.
Could any one explain the best approach to achieve such functionality ?
Below is the code I am using:
Please take a note that I am using AutoMapper to map Object to Entity
public bool ManageUser(UserModel userDetails, string deletedOrders)
{
var isSuccess = false;
try
{
using (var entity = new UserEntity())
{
if (userDetails.UserId == 0)
{
entity.Users.Add(Mapper.Map<User>(userDetails));
}
else
{
var userToEdit = Mapper.Map<User>(userDetails);
foreach (var item in userToEdit.Orders)
{
if (item.OrderId == 0)
{
entity.Entry(item).State = System.Data.Entity.EntityState.Added;
}
else
{
entity.Entry(item).State = System.Data.Entity.EntityState.Modified;
}
}
/***
* How to Write a code here to remove orders using deletedOrders parameter
* Note: deletedOrders contains comma separated Id of the orders which needs to be removed. e.g. "1,5,6"
****/
entity.Entry(userToEdit).State = System.Data.Entity.EntityState.Modified;
}
entity.SaveChanges();
isSuccess = true;
}
}
catch (Exception ex)
{
}
return isSuccess;
}
Note: This is just a simple code. But what if I will have multiple child tables like Order ? If I would follow the same practice than code will become complex and hard to handle. So looking for best approach for such scenarios.

It is not necessary to make a trip to database for entities which should be deleted then.
If userDetails.Orders includes orders which should be deleted, you change their states inf your foreach (var item in userToEdit.Orders) cycle to System.Data.Entity.EntityState.Deleted.
If not, you simply create ones with suitable id's, attach them and then change their EntityState to Deleted as well:
var ordersToDelete = deletedOrders.Split(new[] {','},
StringSplitOptions.RemoveEmptyEntries).Select(x => new Order
{
Id = int.Parse(x.Trim())
})
.ToList();
ordersToDelete.ForEach(o =>
entity.Entry(x).State = System.Data.Entity.EntityState.Deleted);

Related

EF migration,to first select record based on some condition,store it in some varible for later utilization

Say we have a table called as
Employee
___________________________________
ID | Name | Surname | DomainID
And another table
Domain
______________________
ID | Name | Type
where employee table has foreigh key to domain table
Now i want to write Entity Framwwork Migration such that whose domainID matched with filtering criteria and i want to change Domain.Type and say Employee.Surname.
Some thing like
1. var emp = Select all Employee where DomainID = 1;
Store the result in some varibale
2. loop through emp and do changes.
NOTE: I am using EntityFramework, and i dont want to create temporary tables to store data as it might be one time job.
I assume the below will do the trick
private void YourMethod(int domainId)
{
var filteredEmployees = Emoployees.Where(e=>e.DomainID == domainId).ToList();
foreach(Employee emp in filteredEmployees)
{
//do your logic
}
YourDBContext.SaveChanges();
}

How do I insert in LINQ to SQL when I have a foreign key and a unique constraint?

Suppose I have a simple database schema with a customers and orders table with a foreign key from orders to customers, and a unique key on customer name.
Customers
-----------
[CustomerID] INT NOT NULL
[Name] VARCHAR(50) NOT NULL
Orders
-----------
[OrderID] INT NOT NULL
[CustomerID] INT NOT NULL
+------------+------+ +---------+------------+
| CustomerID | Name | | OrderID | CustomerID |
|------------+------+ +---------+------------+
| 1 | John | | 1 | 1 |
+------------+------+ +---------+------------+
I've set up LINQ to SQL entities in the obvious way, with a Customer entity and an Order entity with a one-to-many association from Customer to Order.
The issue I'm having comes when I want to enter a new order for John using my LINQ entities. I thought the way to do this would be to get the Customer entity for John and assign it to my Order entity, then submit that, but it's not working. Here's my C# code to do this.
using (var db = new DataClassesDataContext())
{
Order order = new Order();
Customer existingCustomer = db.Customers.FirstOrDefault(c => c.Name == "John");
if (existingCustomer == default(Customer))
{
Customer customer = new Customer();
customer.Name = "John";
order.Customer = customer;
}
else
{
order.Customer = existingCustomer;
}
db.Orders.InsertOnSubmit(order);
db.SubmitChanges();
}
I have verified that I am indeed assigning existingCustomer to my Order before submitting it, but despite this I still get a unique key constraint error when I attempt to submit.
I'm very new to LINQ to SQL, so I think I'm just going about this incorrectly. How should I implement my code to account for a unique constraint?
The line
db.Orders.InsertOnSubmit(order);
marks the whole object graph for insert. So if you move the line to just below Order order = new Order(); only the order is marked for insert. That means that for a new customer you must call InsertOnSubmit too.
I think your code should be fine. Somehow it tries to insert a new customer but that should not happen.
Can you try it with
Customer existingCustomer = db.Customers.Single(c => c.Name == "John");
and see if you get an exception? In that case there might be something wrong with the DBML for the customer table.
Not helping you with the question but vsince you have a unique constraint on the name Single / SingleOrDefault is better than First/FirstOrDefault.

Updating record not working in LINQ to SQL

I have this sequence generation query that gets the current sequence and increment it to next value. But the increment is not updating. The nextval is always returning 1, the default value from the database
Entity | StartVal | Increment | CurVal | NextVal
----------------------------------------------------
INVOICE | 0 | 1 | 0 | 1
The nextval should be 3, 5, 7 and so on
int nextVal = 0;
using (var db = new MedicStoreDataContext())
{
DAL.LINQ.Sequence seq = (from sq in db.Sequences
where sq.Entity == entity
select sq).SingleOrDefault();
if (seq != null)
{
nextVal = seq.NextVal.HasValue ? seq.NextVal.Value : 0;
seq.NextVal = nextVal + 2;
db.SubmitChanges();
}
}
Have I left something undone?
UPDATE:
Answer: I needed to set the Primary Key and update Sequence class field to include the Primary Key
Usually this is because it hasnt found the unique identifier (or Primary Key) for a table.
In your data descriptions are you sure the table correctly picked up the unique item? - when I first tried this although I had a unique key etc, the table description in c# didnt mark it as unique, so the linq quietly didnt updated it as I had expected, no errors no warnings. Once I corrected the data table in c#, it all went well.
Isn't that the correct behaviour? wouldn't you expect nextVal to be 1 if CurVal is 0? I may be missing something here but it seems like your overcomplicating it a bit. Isn't what you want to do basically
using (var db = new MedicStoreDataContext())
{
DAL.LINQ.Sequence seq = (from sq in db.Sequences
where sq.Entity == entity
select sq).SingleOrDefault();
if (seq != null)
{
seq.CurVal += seq.Increment;
db.SubmitChanges();
}
}
I don't see why you need the whole nextVal bit at all. Please feel free to correct me if I'm wrong.

Problem in Inserting or Updating in many to many relationship EF4

Let's say have 3 tables:
Category
-------------
CategoryID int
Title text
Admin
------------
AdminID int
FullName text
Permission
------------
CategoryID int
AdminID int
AllowAccess bit
When i try to update changes to database i got following exception:
Unable to insert or update an entity because the principal end of the 'KiaNetModel.FK_Permissions_Admins' relationship is deleted.
WHY?
The function that update changes:
public static void SetPermissions(int[] cats, int userId, Entities context)
{
var premissions = from p in context.AdminPremissions where p.AdminID == userId select p;
// Clear all premissions...
foreach (var p in premissions)
{
p.AllowAccess = false;
}
foreach (var c in cats)
{
var es = from e in context.AdminPremissions where e.CategoryID == c && e.AdminID == userId select e;
// If any pre permission was found, set flag = true
if (es.Count() > 0)
es.First().AllowAccess = true;
// Otherwise add new one
else
context.AdminPremissions.AddObject(new AdminPremission() { AdminID = userId, CategoryID = c, AllowAccess = true });
}
}
It's an web application, and when user mark permissions, i could only determine which permissions are set, not all of them.
If you have any other idea, or better way please tell me.
I think relationship between tables Permission and Admin has been deleted from either Actual database or from Entity Model. It it is the case then u have to create that relationship again.
Generate "Admin" Table And "Permission" Drop And Create Script (With Data - If U Have Data On it).
Then Execute It, If U Have Relation Re Create It,
Ur Prb Must Be Solve.

EntityFramework many-to-many with junction table

I have two tables, in a many-to-many relationship, with a junction table, as follows:
Member MemberGroup Group
========= ============ =======
PK | ID PK | ID PK | ID
| Name | Member | Name
| Group
| MemberSince
I need to add all the members of a specific group to a list box. The group is selected from a data bound combo box. I was looking to do something like this:
listbox1.ItemsSource = DataModel.Members.Where(u=>u.Group == mygroup);
However, the Member entity only contains the MemberGroup entries.... not the actual groups.
What is the best way to do this?
By the way, .NET Framework 3.5, WPF, Entity Framework, C#, SQL Server Compact Edition (2008)
Found the solution.
public partial class Group
{
public ObjectQuery<Member> Members
{
get
{
return (from j in DataModel.MemberGroup
where j.Group.ID == this.ID
select j.Member) as ObjectQuery<Member>;
}
}
}

Categories