I have a database with owner and vehicle tables with a one-to-many relationship. I want to get all vehicle details and map each owner to each vehicle but I must map the query to a BDO. Not sure on the LINQ syntax but I have the code below.
using (var databaseContext = new DBConnection()) {
var vehicles = (from Vehicle in databaseContext.Vehicles
select Vehicle);
return vehicles.Select(x => new VehicleBDO() {
Id = x.Id,
// ... more simple data types
Owner = new OwnerBDO(
x.Owner.Id,
x.Owner.Name)
}).ToList();
}
Creating a new ownerBDO as shown is giving me a MethodNotSupportedException with details:
Only parameterless constructors and initializers are supported in LINQ
to Entities
I'm used to Java and new to LINQ so have no idea how to do it properly, any help would be much appreciated.
It wants you to do something like this:
Owner = new OwnerBDO() { Id = x.Owner.Id, name = x.Owner.Name},
(I don't know the property names for OwnerBDO so I guessed.)
Related
I need to map an EF entity to an entity more suitable for performing business logic operations. To do so, I am using this expression:
var phoneMapper = phone => new BasePhone
{
Id = phone.Id,
Number = phone.Number,
PhoneType = phoneTypeMapper(phone.PhoneType) //Pseudo-Code
}
In this example, the phone type class should have a mapping of its own:
var phoneTypeMapper = phoneType => new BasePhoneType
{
Id = phoneType.Id,
Name = phoneType.Name
}
I want to use phoneTypeMapper within the definition of phoneMapper, how can I do so? I know this is easy to do with a collection:
var phoneMapper = phone => new BasePhone
{
Id = phoneType.Id,
Name = phoneType.Name,
//Now a phone has many phone types
PhoneTypes = phone.PhoneTypes.Select(phoneTypeMapper)
}
Is there a way to do this for a non-enumerable property?
EDIT
I should also mention that I would like for this to not collapse the query until the parent query has collapsed. I.E. I want to just jam this into a select and not have it hit the database every time it needs to pull record status data.
This question already has answers here:
How to flatten nested objects with linq expression
(4 answers)
Linq nested list expression
(2 answers)
Closed 7 years ago.
I have a list of a custom car object List<Car>. The car class has two properties 'BrandName' and 'Models' as defined below.
public class Car
{
public string BrandName {get; set;}
public List<string> Models {get; set;}
}
The data for the 'List` object is populated from an API as below. It returns close to 200 rows. For illustration purposes, the object has been instantiated with two items as below. The object is returned from the API with this structure and I have no control over how the data is structured and sent.
List<Car> listCarObj = new List<Car>(){
new Car(){ BrandName = "Mercedes", Models = new List<string>(){"Class A", "Class E"}},
new Car(){ BrandName = "BMW", Models = new List<string>(){"X Series", "E Series"}}
}
How do I convert this list to an IEnumerable or another List of an anonymous type having data in the below format using Linq?
var obj = new[] {new {brand = "Mercedes", model = "Class A"},
new {brand = "Mercedes", model = "Class E"},
new {brand = "BMW", model = "X Series"},
new {brand = "BMW", model = "E Series"}};
Thanks in advance..
here is a approach with SelectMany and a nested Select
var result = listCarObj.SelectMany(x => x.Models.Select(y => new { model = y,brand = x.BrandName }));
Why don't you make a linq query, in which you select every object from the listCarObj and, for every element from the list, get all the models and return an anonymous type?
Something like:
var obj = from p in listCarObj
from q in p.Models
select new {
brand=p.BrandName,
model = q
};
You can use SelectMany to flatten your Models and then project it like this:-
var result = listCarObj.SelectMany(x => x.Models,
(carObj, model) => new {
carObj.BrandName, model
});
I'm trying to insert data into a primary table and a dependent table at the same time. A database relationship does exist between the two tables, and table Employee have an Identity column as the Primary Key.
I'm trying:
Database.Employee emp = new Database.Employee()
{
x = DateTime.Now,
y = "xxx"
};
Database.Skill skill = new Database.Skill()
{
Skill = "Reading"
};
emp.Skills = skill; //Error on this line
dc.Employees.InsertOnSubmit(emp);
dc.SubmitChanges();
But I get the error that:
Cannot implicitly convert type 'Database.Skill' to
'System.Data.Linq.EntitySet'
It looks like Database.Employee.Skills is a collection, not a single object. I.e. in the model it would look something like:
public class Employee
{
...
public EntitySet<Skill> Skills { get; set; } // collection of skills
}
Your line of code
emp.Skills = skill;
is trying to instantiate a collection as a single instance, so you are getting conversion error.
As such the correct way to add a skill would be something like
emp.Skills.Add(skill);
Exact implementation depends on what Database.Employee.Skills is.
Entity properties can be split across different tables, meaning that a single Entity can have it's columns mapped to different tables. How does one then, in code, retrieve the info on the particular table an entity property is mapped to.
foreach(PropertyInfo pi in typeof(DbContext).GetProperties())
{
if(pi.PropertyType.IsGenericType && pi.PropertyType.Name.Contains("DbSet"))
{
var t = pi.PropertyType.GetGenericArguments().FirstOrDefault();
var tables = t.GetCustomAttributes(true).OfType<TableAttribute>();
foreach (var entityProperty in t.GetProperties())
{
if (entityProperty.GetCustomAttributes(true).OfType<RequiredAttribute>().Any<RequiredAttribute>())
{
var fieldname = entity.Name;
//I need to match this column with the table it belongs to here
}
}
}
}
So far, I have the code below to get at the entity property, from the object itself, how do I determine the particular table the current property is mapped to, in my database? Thanks in advance.
Consider using the OR/M for the actual generation of the SQL you actually need.
var dbContext = new DbContext();
var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
var set = objectContext.Set<Foo>();
var query = from x in set
where {stuff}
select new { x.Bar, x.Baz ...};
var objectQuery = (ObjectQuery)query;
var command = objectQuery.CommandText;
var parameters = objectQuery.Parameters;
I create some items from a class X.
I add them to de base, do SaveChanges and all this...
The class Y has a relationship many-to-many with X.
Using another Context, I create a Y instance, putting into the collection of X the elements I've created.
I add Y to Y entity set, it is fine.
When I do Context.SaveChanges(), I get:
A value shared across entities or associations is generated in more than one location. Check that mapping does not split an EntityKey to multiple server-generated columns.
Have you ever seen this error?
EDIT: at the beginning, I've put 1-to-many, after I've noticed it is in fact many-to-many.
EDIT 2: showing the way this is being done. Unlike many people while using .net, we do use layers (business, data...). This is the test case:
[TestMethod]
public void WorksWithAreaCategories()
{
using (new TransactionScope())
{
//arrange
var context = ContextFactory.Create();
var categoryBusiness = new CategoryBusiness(context);
var category = new Category
{
Name = "TestCategory###"
};
categoryBusiness.Add(category);
var areaBusiness = new AreaBusiness(context);
var area = new Area
{
Name = "TestArea###",
Description = "TestAreaDescription###",
Categories = new List<Category> {category}
};
//act
areaBusiness.Add(area);
//assert
var areaFromDb = areaBusiness.FindById(area.AreaID);
Assert.IsNotNull(areaFromDb.Categories);
Assert.IsTrue(areaFromDb.Categories.Count > 0);
Assert.IsTrue(areaFromDb.Categories.Any(c => c.CategoryID == category.CategoryID));
}
}
They share the same context. The business layers call SaveChanges in the end of each Add.
How I resolved it:
After adding both of them, I established the relationship with Update.
[TestMethod]
public void WorksWithAreaCategories()
{
using (new TransactionScope())
{
//arrange
var context = ContextFactory.Create();
var categoryBusiness = new CategoryBusiness(context);
var category = new Category
{
Name = "TestCategory###"
};
categoryBusiness.Add(category);
var areaBusiness = new AreaBusiness(context);
var area = new Area
{
Name = "TestArea###",
Description = "TestAreaDescription###",
};
areaBusiness.Add(area);
//act
area.Categories = new List<Category> { category };
areaBusiness.Update(area);
//assert
var areaFromDb = areaBusiness.FindById(area.AreaID);
Assert.IsNotNull(areaFromDb.Categories);
Assert.IsTrue(areaFromDb.Categories.Count > 0);
Assert.IsTrue(areaFromDb.Categories.Any(c => c.CategoryID == category.CategoryID));
}
}
When the error says "more than one location", it really means more than one context. Data "belongs" in a specific context and you get problems if you try to move it between contexts.
There are 2 ways to fix it:
Do everything in the same context
When you create the Y instance, read the X elements from disk, so that they are in the same context, before adding the X elements to Y.
EDIT based on comment:
Try using a single save changes.