How do I correctly use EF4 Navigation Properties? - database

I've created a database using the EF4 model-first approach. In my model, there's an N-to-M relationship between two entities:
I've filled my database with some dummy data, including 3 records of type Diagnosis and 3 records of type TreatmentSchema and associations between them. Here's the code snippet I used to do this:
using(var container = new SmartTherapyContainer()) {
var diagnosisA = new Diagnosis() { Id = Guid.NewGuid(), Name = "Diagnosis A" };
var diagnosisB = new Diagnosis() { Id = Guid.NewGuid(), Name = "Diagnosis B" };
var diagnosisC = new Diagnosis() { Id = Guid.NewGuid(), Name = "Diagnosis C" };
container.Diagnoses.AddObject(diagnosisA);
container.Diagnoses.AddObject(diagnosisB);
container.Diagnoses.AddObject(diagnosisC);
var schemaA = new TreatmentSchema() { Id = Guid.NewGuid(), Name = "Schema 1" };
var schemaB = new TreatmentSchema() { Id = Guid.NewGuid(), Name = "Schema 1" };
var schemaC = new TreatmentSchema() { Id = Guid.NewGuid(), Name = "Schema 1" };
container.Schemas.AddObject(diagnosisA);
container.Schemas.AddObject(diagnosisB);
container.Schemas.AddObject(diagnosisC);
diagnosisB.TreatmentSchemas.Add(schemaA);
diagnosisC.TreatmentSchemas.Add(schemaA);
diagnosisC.TreatmentSchemas.Add(schemaB);
diagnosisC.TreatmentSchemas.Add(schemaC);
container.SaveChanges();
}
I verified that the associations are indeed stored in the reference table created through EF4's mapping. However, when I retrieve a Diagnosis via the container.Diagnoses collection later, its .TreatmentSchemas collection is always empty.
I tried debugging into the EF4-generated code and all it does is lazily create said collection, but it doesn't fill it with the associated objects. Ayende's Entity Framework Profiler shows no queries being generated at all when the property is accessed, which leads me to believe that I'm doing something wrong here.
How can I get a list of the associated TreatmentSchemas?

Navigation properties are not loaded by default. You must use either eager loading or lazy loading but because you are using self tracking entities your choice is only eager loading because STEs don't support lazy loading. So if you want to get Diagonstic instance with all related TreatmentSchemas you must call:
var diagnosis = context.Diagnoses.Include("TreatmentSchemas").FirstOrDefault();

Related

Applying filter to a dropdown list - ngoptions

I have a method that returns the list of custom types, those values are being used in both the dropdown lists, but now I want to remove a subset of them based on the type and then add to first drop down. I am using angular js, asp.net mvc. What is the best way to apply filter even before data is being rendered and keeping the same method.
Below is the method in the controller which returns names and departments as a json response. Now I want this method to return two different json objects one with subset of the current set being returned based on department they belong to.
Public JsonResult GetDetails()
{
List<Cust> Customers = new List<Cust>();
Customers = GetCustomerDetails();
var name = Customers.Select(e => new{e.custname}).Distinct().ToList();
var dept = Customers.Select(e => new{e.deptname}).Distinct().ToList();
var response = new{CustomerNames = name, CustomerDepartments = dept};
return Json(response, JsonRequestBehaviour.AllowGet();
}

Error in saving related objects in Entity Framework

I have a structure like this
DRDLines:
ID
DrawingRevisionID
DrawingRevision:
ID
Name
They're related in a one-to-many relationship.
In this code example
DRDLine line;
using (var db = new AMPX_DCEntities())
{
line = db.DRDLines.Single(p => p.ID == 1);
System.Console.WriteLine(line.DrawingRevision.ID);
}
using (var db = new AMPX_DCEntities())
{
var id = 12;
line.DrawingRevisionID = id;
}
using (var db = new AMPX_DCEntities())
{
db.Entry(line).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
}
I get this error
A referential integrity constraint violation occurred: The property value(s) of 'DrawingRevision.ID' on one end of a relationship do not match the property value(s) of 'DRDLine.DrawingRevisionID' on the other end.
What I've found: it doesn't update relations in DRDLines inside DrawingRevision
Debugging I see:
line.DrawingRevision.DRDLines[0].ID != line.DrawingRevisionID
If I remove line
System.Console.WriteLine(line.DrawingRevision.ID);
or write it like this
System.Console.WriteLine(line.DrawingRevisionID);
everything goes without errors. But I need that line to be used.
So, how can I fix that?
My guess is that the problem is caused by repeatedly creating a new context and then disposing it. When you set the DrawingRevisionID here
using (var db = new AMPX_DCEntities())
{
var id = 12;
line.DrawingRevisionID = id;
}
line is detached from the dbcontext from which it was retreived, but isn't attached to the new DbContext you've created, hence EF won't wire up the relationships when you change the ID.
You could attach the line object back to the context before changing the ID
db.DRDLines.Attach(line);
That will change both the IDs (although you could just change the other ID manually). Since that context is then disposed, you may need to set the EntityState to Modified for the DrawingRevision (or at least of the ID property) in the last DbContext session.
Also, I would add an Include to the original query to eagerly load the DrawingRevision. At the moment its only loaded when you query the ID on the System.Console line, hence why the behaviour is different. This also causes an extra trip to the database. Putting it into an include will be more efficient and more predictable.

MVVM database delete Method

I want to DELETE some items from my Model which I generated from the database like that:
db = new TestDBEntities();
foreach (var item in db.Farbe)
{
_model.Add(new Farbe { FarbauswahlNr = item.FarbauswahlNr, Kurztext = item.Kurztext, Ressource = item.Ressource,Vari1 = Convert.ToBoolean(item.Var1) ,Vari2 = item.Vari2 });
}
I'm showing this Model in a RadGridView and deleting by Selecting and Index per Rightcklick on the mouse like this:
public void ExecuteDelete(object obj)
{
farbliste.Model.Remove(SelectedIndex);
ListeAktualisieren();
}
Now the question is how do I Delete something from my Database because if I just Delete from my Model it wont work and that's also not what I want.
Btw some variable are named in German sorry...
you have to save your context. Your context in the first block of code is db.
So:
db = new TestDBEntities();
db.entity.Remove(db.entity.Find(SelectedIndex));
db.SaveChanges();
Entity is the name of your table/object from entity frramework. I would also suggest wraping this is a using block for the db

Updating of BindingSource in WinForms

During my attempts to use DataBinding in Winforms I've encountered with a problem. It looks like after updating of DataSource DataGridView doesn't refresh the data. Can't understand where is a problem.
var companies = new List<Company> { new Company { Name = "Test", Id = 100 }}
And here is the code for binding of items list to DataGridView:
bindingSource1.DataSource = _context.Companies;
dataGridView1.DataSource = bindingSource1.DataSource;
But after that if I update companies list like this
companies.Add(new Company { Name = "MDG", Id = 500 });
I can't find the newly added item into the DataGridView. Could someone help me to understand what I'm missing?
The problem here is that there is no way the BindingSource and the DataGridView can be made aware of changes to a List automatically.
Instead, use a new BindingList(). This has events that will be called to notify the BindingSource, and in turn the DataGridView that a new item to the list has been added.
var companies = new BindingList<Company>();
companies.Add(new Company { Name = "Test", Id = 100 });

Export data as C# / VB format to use them in EF Code First's Database Initialization

Some times, sample data is important but boring to generate due to many related tables.
So, in Entity Framework Code First, I think it's an elegant way to insert them in DropCreateDatabaseIfModelChanges::Seed().
But is there a way to export existing data from database back to a string as C# / VB sentences that insert poco objects?
If it works, we may use it to backup data gracefully, or save to multiple .cs by scenes, switch them as needed to better our test, etc.
DATABASE EXPORTS AS THE FOLLOWING CODE:
var students = new List<Student>
{
new Student { FirstMidName = "Carson", LastName = "Alexander", },
new Student { FirstMidName = "Meredith", LastName = "Alonso", },
new Student { FirstMidName = "Arturo", LastName = "Anand", },
// ...
};
students.ForEach(s => context.Students.Add(s));
context.SaveChanges();
As #Luke suggested in his comment. the best way is to generate Json files for your seed data.
in this article, you can find the easy way to generate your Json from SQL query.
Then all you need is to read them by Newtonsoft.Json
e.g.
var countriesStream = new StreamReader(HostingEnvironment.MapPath("jsonFile.json"));
try
{
countriesList = JsonConvert.DeserializeObject<List<Country>>(countriesStream.ReadToEnd());
}

Resources