How delete collection? - c#

var main = (from d in db.Discounts where d.Id == discount.Id && d.UserId == userId select d).FirstOrDefault();
main.Address = "new address";
main.TermsStocks.Clear(); // I need clear collection and add new object.
foreach (var termsStock in terms)
{
main.TermsStocks.Add(new TermsStock() { Id = Guid.NewGuid(), MainId = main.Id, Title = termsStock.Title });
}
db.SaveChanges();
and I have error:
The operation failed. Unable to change the link because one or more
properties of the foreign key values ​​do not allow NULL. If you
change the connection property of the respective foreign key set to
NULL. If the foreign key value does not support NULL, must be defined
a new relationship, the foreign key property should be set to another
value other than NULL, or to remove unbound object.
how to remove the entire collection and save a new one?

You will have to remove those items form the database as well, not just from the nav property.
Roughly:
// main.TermsStocks.Clear();
foreach (var item in main.TermsStocks)
{
db.TermsStocks.Remove(item);
}

I think TermsStock object has a non nullable foreign key of Discount. Then it is not possible to have a TermsStock object without a Discount. What you are trying to do is not possible in this manner.

Related

Create object from existing object Entity framework c#

I want to copy full information of record to another in EF C#:
List<Cohort> AnYearsCohorts = oDB.Cohorts.Where(x=>x.Year == oCh.Year).ToList();
foreach (Cohort ochort in AnYearsCohorts)
{
Cohort nChort = new Cohort();
nChort = ochort;
nChort.Year = Year;
nChort.ID = 0;
oDB.Cohorts.Add(nChort);
}
oDB.SaveChanges();
But got following error:
{"The property 'ID' is part of the object's key information and cannot
be modified. "}
You probably have set ID as primary key and auto incremented so you can not change ID field explicitly in code.
Either remove ID as key or let ID increment automatically.

Does Entity framework accept/add data of an int PK that is not auto-incremented?

I have a table that has an int PK and I did not implement auto-incrementation for it. I wanted to add the data from my client application. If I try to add without auto-incremented int PK I get this exception:
An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
Additional information: The property 'id' is part of the object's key information and cannot be modified.
Inner exception:
The property 'id' is part of the object's key information and cannot
be modified.
Well, I'm not modifying anything. I'm just trying to add a line. What's going on?
EDIT
As per request here's my code
var size = new IMF_Size();
foreach (var item in sizeFromConsolidator)
{
if (anthill.IMF_Size.Where(w => w.Brand == item.Brand && w.Category == item.Category && w.SizeCode == item.SizeCode).Count() == 0)
{
size.id = item.id;
size.SizeCode = item.SizeCode;
size.Name = item.Name;
size.Brand = item.Brand;
size.Category = item.Category;
anthill.IMF_Size.Add(size);
anthill.SaveChanges();
}
}
Your construction of size is outside of the loop.
The first time you get to the size.id = item.id; line, your size is a new entity. You set its properties, you add it to anthill, and you save the changes.
Then you go through the loop again. You get to the size.id = item.id; line again. But you haven't constructed a new size. You really are modifying an existing entity at that point.
That's exactly what the exception is telling you, too. Move the construction of size to within the loop.
Put this over the propierty of the class to DB like says Prasad Kanaparthi
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }

How can I edit or add to a particular field without pull the all object

How I can do just this ( a.myFavorits.Add()) without pulling the all object to var a , because a has a lot of data, and I don't want to pull all a object, but I can't find a way do do it.
I want to do the lambada and the linq without return something but linq is always return something
public static void addFavorits(long f,long idUser)
{
using (var db = dataBase())
{
// here i pull object user from users table
var a = db.users.Where(c => c.id == idUser).SingleOrDefault();
// here i adding to the object field myFavorits new value
//myFavorits is also a table of entitys that connected to user object
a.myFavorits.Add(new BE.FavoritsUsersLong { myLong = f });
db.SaveChanges();
}
}
I thought to do something like this but i dont know how to set the field users_TableId that is the key that connect the 2 tables
public static void addFavorits(long favoritId,long idUser)
{
using (var db = dataBase())
{
db.favoritsUsersLong.Add(new BE.FavoritsUsersLong {myLong = favoritId}
/*,users_TableId =idUser*/);
db.SaveChanges();
}
}
Here's a concrete example that does what you want. In this example, only the Name of a Company is modified and saved. Or an item is added to one of its collections.
var cmp = new Company{ CmpId = 1, Name = "Cmp1" }; // CmpId is the primary key
db.Companies.Attach(cmp);
db.Entry(cmp).Property(c => c.Name).IsModified = true;
// Or add an entity to a collection:
cmp.Users = new[] {new User { Name = "a1", PassWord = "a1" } };
try
{
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
}
finally
{
db.Configuration.ValidateOnSaveEnabled = true;
}
Result in SQL:
DECLARE #0 VarChar(30) = 'Cmp1'
DECLARE #1 Int = 1
UPDATE [dbo].[Company]
SET [Name] = #0
WHERE ([CmpId] = #1)
There are a few things to note here:
Obviously you need to know the Id of the entity you want to modify.
The object you create is called a stub entity, which is an incomplete entity. When you try to save such an entity, EF is very likely to complain about null values in required properties. That's why almost certain you'd have to disable validation (temporarily, or, better, dispose the context immediately).
If you want to add an item to a collection, you should leave validation enabled, because you'd want to know for sure that the new entity is valid. So you shouldn't mix these two ways to use a stub entity.
If you often need roughly the same small part of your entity you may consider table splitting.
I'm guessing this is what you want? I don't see you 'editting' I only see you adding.
using (var db = dataBase())
{
var a = new user();
....
//set properties etc..
...
a.myFavorits.Add(new BE.FavoritsUsersLong { myLong = f });
db.users.Add(a);
db.SaveChanges();
}

Entity Framework Update error

I am getting a voialation of Primary key error with the following code. I can't see for looking as to why this may be and I need to sort it out. Can anybody help with a fresh pair of eyes?
var events = (from e in nodes.Descendants("event")
select new Event
{
Event_ID = int.Parse(e.Attribute("event_id").Value),
Name = e.Attribute("name").Value,
Code = e.Attribute("code").Value,
Minute = e.Attribute("minute").Value != String.Empty ? int.Parse(e.Attribute("minute").Value) : 0,
Minute_Extra = e.Attribute("minute_extra").Value != String.Empty ? int.Parse(e.Attribute("minute_extra").Value) : 0,
Team = GetTeam(e.Attribute("team_id")),
Last_Updated = DateTime.Parse((FormatDateTime(e.Attribute("last_updated").Value)))
});
foreach (Event matchEvent in events)
{
//Check to see if this event exists
if (match.Events.Any(o => o.Event_ID == matchEvent.Event_ID))
{
Event theEvent = (from m in match.Events
where m.Event_ID == matchEvent.Event_ID
select m).FirstOrDefault();
//There is an event with this ID, so check its last updated flag
if (theEvent.Last_Updated < matchEvent.Last_Updated)
{
//Update the current event
theEvent.Event_ID = matchEvent.Event_ID;
theEvent.Name = matchEvent.Name;
theEvent.Code = matchEvent.Code;
theEvent.Minute = matchEvent.Minute;
theEvent.Minute_Extra = matchEvent.Minute_Extra;
theEvent.Team = matchEvent.Team;
theEvent.Last_Updated = matchEvent.Last_Updated;
}
}
//If the event is not there we need to add it
else
{
match.Events.Add(matchEvent);
}
myDb.SaveChanges();
UPDATE 1: The following is the error I get when SaveChanges() is called:
{"Violation of PRIMARY KEY constraint 'PK_Matches_1'. Cannot insert duplicate key in object 'dbo.Matches'.\r\nThe statement has been terminated."}
UPDATE 2: I am not using identity insert on the DB table for this as this is an import from a 3rd party Web Service where I need to retain all Ids. I am not sure if this will affect the update process with entity framework?
UPDATE 3: Ok well when I turn on identity insert the update is successful however I dont wish to have indentity insert on this table as the Ids are passed in from a WebService and I need to retain these Ids.
I'm not sure, because I'm not too hot on Entity Framework, but do you need this line?
theEvent.Event_ID = matchEvent.Event_ID;
It comes just after
//There is an event with this ID, so check its last updated flag
if (theEvent.Last_Updated < matchEvent.Last_Updated)
and I would think it's redundant, and also might cause a Primary Key error, as I don't think you can assign to a primary key once it's been created.
Update
Did a quick search, and you can't update a primary key once it's been created, so I'm pretty sure this is where your error is.
See this SO answer: Update primary key value using entity framework
I believe that your problem lies when you are updating the Event_ID property. The object you requested from your database through the match DBContext already contains that same Event_ID as the Web service. Therefore, there is no need to update this value
if (theEvent.Last_Updated < matchEvent.Last_Updated)
{
//Update the current event
theEvent.Event_ID = matchEvent.Event_ID; // <-- Delete this line.
...
}
You may ask, why it matters since both values are the same? As it so happens the DBContext keeps track of your objects and its changes. In the context itself, each property has an original and current value. When you assigned the same value to the Event_ID the context is going to interpret it as a compleately different value even though is the same.
I hope this helps.

LINQ to SQL Insert Multiple Tables Question

I have 3 tables. A primary EmploymentPlan table with PK GUID EmploymentPlanID and 2 FK's GUID PrevocServicesID & GUID JobDevelopmentServicesID. There are of course other fields, almost exclusively varchar(). Then the 2 secondary tables with the corresponding PK to the primary's FK's.
I am trying to write the LINQ INSERT Method and am struggling with the creation of the keys. Say I have a method like below. Is that correct? Will that even work? Should I have seperate methods for each?
Also, when inserting I didn't think I needed to provide the PK for a table. It is auto-generated, no?
Thanks.
public static void InsertEmploymentPlan(int planID, Guid employmentQuestionnaireID, string user, bool communityJob, bool jobDevelopmentServices, bool prevocServices, bool transitionedPrevocIntegrated, bool empServiceMatchPref)
{
using (var context = MatrixDataContext.Create())
{
var empPrevocID = Guid.NewGuid();
var prevocPlan = new tblEmploymentPrevocService
{
EmploymentPrevocID = empPrevocID
};
context.tblEmploymentPrevocServices.InsertOnSubmit(prevocPlan);
var empJobDevID = Guid.NewGuid();
var jobDevPlan = new tblEmploymentJobDevelopmetService()
{
JobDevelopmentServicesID = empJobDevID
};
context.tblEmploymentJobDevelopmetServices.InsertOnSubmit(jobDevPlan);
var empPlan = new tblEmploymentQuestionnaire
{
CommunityJob = communityJob,
EmploymentQuestionnaireID = Guid.NewGuid(),
InsertDate = DateTime.Now,
InsertUser = user,
JobDevelopmentServices = jobDevelopmentServices,
JobDevelopmentServicesID =empJobDevID,
PrevocServices = prevocServices,
PrevocServicesID =empPrevocID,
TransitionedPrevocToIntegrated =transitionedPrevocIntegrated,
EmploymentServiceMatchPref = empServiceMatchPref
};
context.tblEmploymentQuestionnaires.InsertOnSubmit(empPlan);
context.SubmitChanges();
}
}
I understand I can use more then 1 InsertOnSubmit(), See this question, I just don't understand how that would apply to my situation and the PK/FK creation.
The pk can be auto generated when the table's definition in the db does it for you. Also the property for the corresponding pk on the linq model has to configured to be updated after the insert, so it gets the auto generated ID.
I don't think the relation on those tables is on your linq model. Otherwise you should be able to do:
using (var context = MatrixDataContext.Create())
{
var empPlan = new tblEmploymentQuestionnaire
{
CommunityJob = communityJob,
InsertDate = DateTime.Now,
InsertUser = user,
JobDevelopmentServices = jobDevelopmentServices,
JobDevelopmentService = new tblEmploymentJobDevelopmetService(),
PrevocServices = prevocServices,
PrevocService = new tblEmploymentPrevocService(),
PrevocServicesID =empPrevocID,
TransitionedPrevocToIntegrated =transitionedPrevocIntegrated,
EmploymentServiceMatchPref = empServiceMatchPref
};
context.tblEmploymentQuestionnaires.InsertOnSubmit(empPlan);
context.SubmitChanges();
}
ps. not having the relation in the model is a design decision, so the above doesn't mean that's the only way to do it. The way you showed (with the extra SubmitChanges calls as in the other answer) is perfectly valid, just responds to a different design.
I think the issue is (if I understand it correctly) you are deferring the inserting, except you don't know it...
Since you're creating FKs but differing their insertion until the end, it doesn't know what to do, so when you try to create the main entry it's enforcing the FK constraints (which might not exist yet), thus failing. Try creating the FK entries and actually submitting the changes to the database before insert the main entry.
For example, say you have the following tables:
Child
Toy
ToyOwner
ToyOwner has FK constraints on Child and Toy. If the entries are missing in that table, you will not be able to insert an entry into ToyOwner. So you'd have to do something like the following:
Child myChild;
Toy myToy;
//Queue up the changes that are going to be submitted
InsertOnSubmit(myChild)
InsertOnSubmit(myToy)
//Submit the queue
SubmitChanges();
//Now that those FKs are filled, we can insert the main entry with those FK values
ToyOwner = new myToyOwner
myToyOwner.Child = myChild
myToyOwner.Toy = myToy
//And insert the new queue into the DB
InsertOnSubmit(myToyOwner)
SubmitChanges();

Categories

Resources