I have a small ASP.NET MVC application with the following entity objects:
Person
PersonId
Name (string)
FirstName (string)
Country (Country)
Country
CountryId
Name
I can add and delete the entity's this works fine. I can also update name, firstname.
But how can i update the country property with another country.
i was trying
p.Country = (from c in db.Country
where c.CountryId == countryId
select c).First();
but this fires an exception {"An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key."}"
even before i call SaveChanges on the datacontext.
Can someone explaind how i can update this property?
kind regards
Dieter
Is db your context? You should be able to do:
p.Country = ctx.Country.First(c => c.CountryId == countryId);
Or, if you don't want to query the database to get the foreign key entity you can also use an EntityKey to the same effect:
p.CountryReference.EntityKey = new EntityKey("MyDb.Country", "CountryId", countryId);
Code similar to this has worked for me when updating navigation properties.
Country country = new Country{CountryId = theNewCountryID };
db.AttachTo("Countries", country);
p.Country = country;
db.Savechanges();
Create a stub of the new country then attach it to the countries EntitySet, assign the new country to your Entity's navigational country property and call SaveChanges().
Use your country EntitySet name in the AttachTo call.
This is what worked for me. In the model:
<%= Html.Textbox("Country.CountryId", Model.Countries) %> // I'm using a form model view
In the controller:
Person originalPerson = (from p in db.PersonSet
where p.PersonId == updatedPerson.PersonId
select p).First();
Country country = (from c in db.CountrySet
where c.CountryId == updatePerson.Country.CountryId
select c).First();
db.Attach(country);
originalPerson.Country = country;
db.ApplyPropertyChanges(originalPerson.EntityKey.EntitySetName, updatedPerson);
db.Savechanges();
I used the second solution and I got no exception, but the CountryId wasn't changed in the database even after I called AcceptChanges.
Related
Is there any better way to merge a Entity Table with a Entity View
A little example: I have a Person table with:
id,
name,
lastname
columns and a view named ViewPersonLastLocations with:
person_id
location_name.
I need to display Person table with the information of ViewPersonLastLocations.
Actually i can "merge" those entities with two foreachs, and i create a variable in the Person partial class.
Is there any other way to do this?
I am a little unclear on what you want based on your last comment, but will start with this code for a join if the relationship is 1:1. If it is 1:Many, then it is similar, but project into a collection.
var personWithLocation = context.Persons
.SelectMany(p => context.ViewPersonLastLocations
.Where(vp => vp.person_id == p.id)
.DefaultIfEmpty(),
(p, vp) => new PersonViewModel // create a viewmodel for results or anonymous
{
Id = p.id,
Name = p.name,
LastName = p.lastname,
LocationName = vp.location_name
}
).ToList();
When I call this linq query I get the following error:
The entity or complex type 'DataModel.CustomerContact' cannot be constructed in a LINQ to Entities query.
I don't understand what I am doing wrong here. Normally when I am not joining with any other tables and have no navigation properties I would typically just select cc, but in this case I need to create a new CustomerContact object so I can bind the navigation properties.
I did some research on this and is there really no way to do this? If I use an anonymous type how do I convert to to a CustomerContact since I need to ultimately return a list of CustomerContact to my application? If I simply select cc then cc.CustomerName will not get set. I am really trying to avoid creating Dtos when I should just be able to use the auto-generated EF object classes.
public static IEnumerable<CustomerContacts> GetList(int customerId = null)
{
using (var context = new AppContext())
{
var cList = (from cc in context.CustomerContacts
join c in context.Customers on cc.CustomerId equals c.Id
where (customerId == null || cc.CustomerId == customerId)
select new CustomerContact
{
Id = cc.Id,
FirstName = cc.FirstName,
LastName = cc.LastName,
Email = cc.Email,
// navigation properties
CustomerName = c.Name
}).ToList();
return objList;
}
}
If I simply select cc then cc.CustomerName will not get set
You could do:
from cc in context.CustomerContacts.Include(cc => cc.CustomerName)
...to get the navigation property loaded automatically for you. Search for "EF navigation properties lazy loading".
Note, you need to have 'using ...some namespace I can't remember' to get that syntax to work because it uses an extension method. Otherwise you can just quote the name of the navigation property you want to load, as in:
from cc in context.CustomerContacts.Include("CustomerName")
Let's say I have an entity and a db table named Client.
Client has a foreign key - CountryId that connected to the Countries table.
ClientA, ClientB and ClientC inherit from Client.
I want to list all the clients in my system (including those with null countryId), along with their concrete types (the discriminator value) and the country name.
My query looks something like this:
from client in DbContext.Set<Client>()
from country in DbContext.Set<Country>().Where(x => x.Id == client.CountryId).DefaultIfEmpty()
where !(client is Salon)
select new
{
Id = client.Id,
Name = client.ClientName,
ClientClass = "TODO",
CountryName = country.CountryName
};
My question: How can I select the discriminator value? Note the "TODO" in the code where I'm stuck at the moment..
Thanks!
discriminator column is used internally by Code First and you cannnot read/write its values from an inheritance mapping standpoint.
to get decriminator you have to create custom SQL query
context.Database.SqlQuery<T>("SELECT client.Id, client.ClientName, client.Discriminator, country.CountryName FROM Countries country LEFT JOIN Clients client ON country.Id = client.CountryId WHERE client.Discriminator <> 'salon'").ToList()
I am creating App using Entity Framework.I have loaded the Database model from Database.here In the Course table Department is the Navigation Property,DepartmentID is the foreign key.I have created a gridview and set its Datasource to Course Table,but I want to see the Deaptment Name instead of department ID.I can use the Navigation properties like Department.count but how can I use the navigation property to get data (Department name) from Department Table.
Any one who can help me with this
THIS IS MY CODE
var result = (from o in ctx.Courses.Include("Department")
where o.Title == TextBox2.Text
select o
).First();
//GridView4.DataSourceID="";
GridView3.DataSource=result;
GridView3.DataBind();
If I dont use the First Function then i can't access the Department Name attribute,If i use the First() It say that
Data source is an invalid type. It must be either an IListSource, IEnumerable, or IDataSource.
please tell me how i can solve it?
I think Products and Categories tables in Northwind are similar than your need. I would write a query like this:
var ctx = new NorthwindEntities();
var query = from prod in ctx.Products
where prod.ProductName.StartsWith("C")
select new { prod.ProductName, prod.UnitPrice, prod.Category.CategoryName };
var result = (from c in dbContext.Course
select c).First();
if(!result.Department.IsLoaded)
{
result.Department.Load(); //this will load the course.Department navigation property
}
//Assuming you have 1 - 1 relationship with course to department
string departmentName = result.Department.Name;
or if you have 1 - M relationship with the department then:
foreach(Department d in result.Department)
{
Console.WriteLine(d.Name);
}
EDIT:
Instead of trying to load Department do the following
if(!result.DepartmentReference.IsLoaded)
{
result.DepartmentReference.Load()
}
How to: Explicitly Load Related Objects
I know I've seen this but I cant find it anywhere.
I have a couple objects with a many-to-many relationship: Person and Department. A person can have many departments and vice versa.
I thought it was:
var person = //query user
var d = new Department();
d.Id = 123;
person.Departments.add(d);
This creates a new department in the database and links them but that isnt what I want. The department already exists. I just want to create the relationship. How can I do this without having to requery the database to get an instance of the department?
Try this:
var department = dbContext.Departments.FirstOrDefault(d => d.Id == 123);
person.Departments.Add(department);
dbContext.SaveChanges();
This shouldn't query the database until dbContext.SaveChanges() is called as deferred querying is used. However, if that doesn't work, you can try updating the mapping entity directly instead:
var departmentMember = new DepartmentMember
{
DepartmentId = 123,
MemberId = person.Id
};
dbContext.DepartmentMembers.Add(departmentMember);
dbContext.SaveChanges();
How about:
person.Departments.Add(context.Departments.First(c=>c.Id==123));