How to fetch data with EF on one to many relationship.i.e if i have a table name Person(personID as primary key) and another table name streetLivedIn(personID as foreign key).
Now i force my controller method to pass an object of type person
var persons=db.persons();
return View(persons);
Now i want to display Person details along with street(i.e that what stored at streetLivedInTable) he/she lived at.suppose i have an Entityset of person
public class Persons
{
public string Name{get;set;}
//NAVIGATIONL PROP.
public virtual ICollection<streetLivedIn>{get;set}
}
Suppose the navigational property name is Streets.
public class Persons
{
public string Name { get; set; }
//NAVIGATIONL PROP.
public virtual ICollection<streetLivedIn> Streets { get; set }
}
Then you can use the Include method to eager load this property.
var persons = db.persons.Include("Streets");
return View(persons);
You can display this in various ways. Eg
#foreach (var person in Model)
{
<div>#person.Name</div>
#foreach (var street in person.Streets)
{
<div>#street.Name</div>
}
}
Or you can use the WebGrid, MvcContrib Grid, etc
Assuming you don't want to expose the Entity Framework data model directly to the view, and instead do a conversion to business objects you create, I would simply iterate the EF datamodel with a double foreach loop. Entity Framework creates the one-to-many-references for you using containment - why not take advantage of that.
I prefix the EF-generated classses with "Ef" for clarity.
var personList = new List<Person>();
foreach (var efPerson in EfPersons)
{
var person = new Person
{
Name = efPerson.Name,
StreetsLivedIn = new List<StreetLivedIn>();
}
foreach (var efStreet in efPerson.EfStreetsLivedIn)
{
var street = new StreetLivedIn { Name = efStreet.Name; }
person.StreetsLivedIn.Add(street);
}
personList.Add(person);
}
return View(personList);
Related
I have this model that joints two table cars and model. I can only see the data within the model. So if it returns two models it will on only display one record. I am trying to have to return a list of objects?
Model
public class CarsJoinModel
{
public Cars Cars { get; set; }
public Model Model { get; set; }
}
IQueryable<CarsJoinModel> GetCarsAndModel();
The name Select does not exist in the current context
Model = t.Model
.Select(entry => new
{
DisplayName = entry,
Model = entry.
}).ToList(),
This is working but will I will need this to be a list
Model = t.Model.DisplayName
Updated
var CarsModel = (from c in UnitOfWork.GetRepository<Cars>().Get()
join m in UnitOfWork.GetRepository<Model>().Get() on c.Id equals m.CarId
select new CarsModel
{
Car = c,
Model = m
}
);
public class CarsModel
{
public CarsCars{ get; set; }
public IEnumerable<Model> Model{ get; set; }
}
I assume you are using EntityFramework here. Normally you would somehow relate those two things together and if one was a child of the other, you could just .Include() it and both would be hooked up. If not, then you have to go manually load each instance and build up this Model you are returning yourself. EF won't do it for you. It won't be able to project those two separate entities the way you want. The only way I think you could make it work would be a painful/chatty experience. Also, if you leave it as IEnumerable or don't do .ToList(), the query doesn't run so if the context is killed below before it has a chance to run, you will also be in trouble. Hopefully you can do this, but I don't know your model:
var result = UnitOfWork.GetRepository<Cars>().Get().Include(a => a.Models).ToList();
return result.Select(a => new CarsModel { Car = a, Models = a.Models }).ToList();
If that doesn't work, then you need the more painful/slow way:
var cars = UnitOfWork.GetRepository<Cars>().Get().ToList();
var result = new List<CarsModel>();
foreach (var car in cars)
{
result.Add(new CarsModel { Cars = car, Model = UnitOfWork.GetRepository<Models>().Get(a => a.CardId == car.Id).ToList() }); // Assuming .Get() can take a filter
return result;
}
I have an empty sql table which contains around 100 column headers (fields), using database first approach I have created a single class with all the 100 fields as properties. Now I want to select only 10 fields out of all the properties and insert some data to those fields, such that the existing table should have the inserted data for only those 10 columns and the remaining columns should be updated with NULL. For instance,
public class Product
{
public int UniqueID {get; set;}
public string ProductName {get; set;}
public string type {get; set;}
etc......
}
Now I want the table should be updated with only UniqueID and ProductName and all the remaining fields should have NULL.
I am thinking of using Dictionary<string,object>, to add all the selected properties to dictionary and pass it to the database table.
Please share some ideas on how to implement this scenario using Entity Framework.
If it is MVC and you want to add/edit a subset use a view model:
// this is a viewmodel intended for a particular view, for example AddProductSubset.chtml
public class AddProductSubsetViewModel
{
public int UniqueID {get; set;}
public string ProductName {get; set;}
// add other properties you will be updating from the entity model
// you can also add properties from other entities or things only needed by the view
}
[HttpGet]
public ActionResult AddProductSubset(AddProductSubsetViewModel vm)
{
var vm = new AddProductSubsetViewModel();
// fill in any default values before add/edit
return View(vm);
}
[HttpPost]
public ActionResult AddProductSubset(AddProductSubsetViewModel vm)
{
if (ModelState.IsValid)
{
// map your viewmodel to the entity model. See automapper.
var product = new Product
{
UniqueID = vm.UniqueID, // unless this is identity, then omit
ProductName = vm.ProductName,
otherfield = vm.otherfield,
...
// unmapped entity fields will be set to their default (null, etc)
}
context.Products.Add(product);
context.SaveChanges();
return RedirectToAction("Index")
}
return View(vm);
}
You can reflect and hydrate properties to an instance, then add I think. This should do it
public void ReflectIntoModel<T>(Dictionary<string, object> dic)
{
T m = (T)Activator.CreateInstance(typeof(T));
var prop = typeof(T).GetProperties();
foreach (var a in prop)
{
dynamic val;
if (dic.TryGetValue(a.Name, out val))
a.SetValue(m, val);
}
}
Just make sure you're careful with typing the value, and the fact that the field names are case sensitive
I have a data class with nested Lists. A simplified example (not real code):
public class Movie
{
public Int32 TVIndex;
public string MovieName;
public string MovieRating;
public string MovieRuntime;
public List<Actor> MovieActors;
public List<MovieArt> MovieImages;
}
public class Actor
{
public string ActorName;
public string ActorRole;
}
public class MovieArt
{
public string ImagePath;
}
List<Movie> myMovies = new List<Movie>();
This may contain many movies and each movie may contain many Actors and many MovieArt.
I pass this list to a web service that inserts the records into tables using DataEntityModel.
Something Like..
public void InsertMovies(List<Movie> request)
{
using (TransactionScope scope = new TransactionScope())
{
using (MyMovieStorageEntities DbContext = new MyMovieStorageEntities())
{
foreach (Movie m in request)
{
Movies movie = new Movies();
movie.MovieName = m.MovieName;
movie.MovieRating = m.MovieRating;
movie.MovieRuntime = m.MovieRuntime;
DbContext.DBMovies.Add(movie);
foreach (Actor a in m.MovieActors)
{
Actors actor = new Actors();
actor.ActorName = a.ActorName;
actor.ActorRole = a.ActorRole;
DbContext.DBActors.Add(actor);
}
for (MovieArt i in m.MovieImages)
{
MovieArt artwork = new MovieArt();
artwork.FileName = i.FileName;
DbContext.DBMovieArt.Add(artwork);
}
}
DbContext.SaveChanges();
}
}
}
In the Movie table is an Identity column and I need to return the identity for each inserted record for use in the client app.
I am new to DataEntity and not really sure where to start. All the searching I have done hasn't really helped. Any pointers?
Don't lose the references to your entity framework objects (e.g. add them to a list), and after SaveChanges(), the object property containing the primary key will be automatically updated with the ID.
See here for more info
How can I get Id of inserted entity in Entity framework?
EF automatically returns the ID. movie.ID gives you the last inserted ID you can use it or return it from your method to use somewhere else.
I am having trouble with foreign key relationships in the entity framework. I have two tables: Persons and Countries. Persons has a foreign key column to CountryId.
As the Countries table rarely changes, I want to fetch its data only once, dispose the DatabaseContext, and keep the list of Countries cached somewhere. This is where I am running into problems.
The entity framework seems to want you to open a database context, add/edit rows as needed, then close the database context. If you open, fetch data, close; and then later open, save data, close; it has trouble.
So my POCO objects look like this:
public class Country {
public int CountryId {get; set; }
public String Name {get; set; }
}
public Person {
public int PersonId {get; set; }
public virtual Country Country {get; set; }
}
Then, I try to create a new person like this:
Country[] countries;
using (var dt = new DatabaseContext())
{
countries= dt.Countries.ToArray();
}
Person person = new Person();
person.Country = countries[0];
using (var dt = new DatabaseContext()) {
dt.Entities.Add(person);
dt.SaveChanges();
}
On save, the entity framework creates a new row in the Countries table with the same name as countries[0], but a new, incremented ID. This is obviously not the desired outcome - the person should have its Country_CountryId field set to the id of countries[0], and a new row should not be created.
How do I solve this? I think one solution would be to force the entity framework to not create a new row when it is given an object that already has its primary key set. Is there a way to do this?
I wonder if you at least search little bit on Internet before you put quite big effort to describe the issue because this is very common problem asked every few days.
Add method adds all entities in the entity graph. So if you connect country to person and country is not attached to current context, calling Add on the person will mark both person and country as new entities for insertion. If you don't want country to be inserted you must tell EF that country is not a new entity:
Person person = new Person();
person.Country = countries[0];
using (var dt = new DatabaseContext()) {
dt.Entities.Add(person);
dt.Entry(person.Country).State = EntityState.Modified;
dt.SaveChanges();
}
I have solved this problem by adding the following two methods to my DatabaseContext class:
public void Add(object target)
{
this.Set(target.GetType()).Attach(target);
this.Entry(target).State = System.Data.EntityState.Added;
}
public void Modify(object target)
{
this.Set(target.GetType()).Attach(target);
this.Entry(target).State = System.Data.EntityState.Modified;
}
Short version:
Is it possible in NHibernate to create a mapping for a class that has no corresponding table in the database and specify for each property where the data should come from?
Long version:
I have the following class:
public class TaxAuditorSettings
{
private readonly IList<Month> _allowedMonths = new List<Month>();
private readonly IList<Company> _allowedVgs = new List<Company>();
public IList<Month> AllowedMonths
{
get { return _allowedMonths; }
}
public IList<Company> AllowedVgs
{
get { return _allowedVgs; }
}
}
The class Company is a normal entity that is mapped to a table.
The class Month is a simple class without ID or existing mapping (Constructor and error checking removed for brevity):
public class Month
{
public int MonthNumber { get; set; }
public int Year { get; set; }
}
My database has the following two tables:
Table TAX_AUDITOR_ALLOWED_COMPANIES has only one column COMPANY_ID that is a FK to the table COMPANY and has a UNIQUE index.
Table TAX_AUDITOR_ALLOWED_MONTHS has two columns MONTH_NUMBER and YEAR. There is a UNIQUE index spanning both columns.
I would like to map TaxAuditorSettings such that I can ask my NHibernate session for an object of this type and NHibernate then should put the contents of TAX_AUDITOR_ALLOWED_MONTHS into the list TaxAuditorSettings.AllowedMonths and the companies referenced in TAX_AUDITOR_ALLOWED_COMPANIES into the list TaxAuditorSettings.AllowedCompanies.
Is this even possible? If so, how? If not, how would you do it instead?
Please note: I can change the database if necessary.
not quite what you requested for but here goes
public TaxAuditorSettings GetAuditorSettings(ISession session)
{
// assuming there is a ctor taking the enumerables as parameter
return new TaxAuditorSettings(
session.CreateSQLQuery("SELECT MONTH_NUMBER, YEAR FROM TAX_AUDITOR_ALLOWED_MONTHS")
.SetResultTransformer(new MonthResultTransformer())
.Future<Month>(),
session.CreateCriteria<Company>()
.Add(NHibernate.Criterion.Expression.Sql("Id IN (SELECT COMPANY_ID FROM TAX_AUDITOR_ALLOWED_COMPANIES)"))
.Future<Company>())
}
class MonthResultTransformer : IResultTransformer
{
public IList TransformList(IList collection)
{
return collection;
}
public object TransformTuple(object[] tuple, string[] aliases)
{
return new Month
{
MonthNumber = (int)tuple[0],
Year = (int)tuple[1],
}
}
}
Update: saving
public void SaveOrUpdate(ISession session, TaxAuditorSettings settings)
{
using (var tx = session.BeginTransaction())
{
// get whats in the database first because we dont have change tracking
var enabledIds = session
.CreateSqlQuery("SELECT * FROM TAX_AUDITOR_ALLOWED_COMPANIES")
.Future<int>();
var savedMonths = session
.CreateSQLQuery("SELECT MONTH_NUMBER, YEAR FROM TAX_AUDITOR_ALLOWED_MONTHS")
.SetResultTransformer(new MonthResultTransformer())
.Future<Month>();
foreach (var id in settings.AllowedVgs.Except(enabledIds))
{
session.CreateSqlQuery("INSERT INTO TAX_AUDITOR_ALLOWED_COMPANIES Values (:Id)")
.SetParameter("id", id).ExecuteUpdate();
}
foreach (var month in settings.AllowedMonths.Except(savedMonths))
{
session.CreateSqlQuery("INSERT INTO TAX_AUDITOR_ALLOWED_MONTHS Values (:number, :year)")
.SetParameter("number", month.Number)
.SetParameter("year", month.Year)
.ExecuteUpdate();
}
tx.Commit();
}
}
Note: if you can change the database it would be much easier and performant to sanitise the tables
I would do it this way.
public class MonthMap : ClassMap<Month>{
public MonthMap(){
CompositeId()
.KeyProperty(x=>x.MonthNumber,"MONTH_NUMBER")
.KeyProperty(x=>x.Year);
Table("TAX_AUDITOR_ALLOWED_MONTHS");
}
}
Add a column to the COMPANY table called TaxAuditable and map it to a bool property. Update the column to be 1 where a matching row is found in TAX_AUDITOR_ALLOWED_COMPANIES. Then remove the table TAX_AUDITOR_ALLOWED_COMPANIES as it serves no real purpose.
Now you have a Company with an appropriate property on it you can query Company's where TaxAuditable is true and pass them into a method along with the Months to do your work/calculations etc... Something like this perhaps?
var taxAuditableCompanies = session.QueryOver<Company>()
.Where(x=>x.TaxAuditable==true).Future();
var months=session.QueryOver<Month>().Future();
var myService = new MyService();
myService.DoSomeWork(taxAuditableCompanies, months);