Hi people of the internet,
I've been searching on SO for a couple of days now, tried loads of possible solutions but I'm not able to solve my issue in the following test-project. Please excuse my lack of skill as I'm a self-taught programmer for just over a year now and I'm this is my first question on SO.
The situation:
I've got 2 entity classes Car and Wheel and want to store and query them from a single db table using c#'s linq to sql(ite).
public class Car
{
public Int64? Id { get; private set; }
public string Manufacturer { get; private set; } = "Porsche";
public double Mileage { get; private set; }
public Wheel Wheel { get; private set; }
public Car()
{
this.Id = Program.CarCount;
Mileage = new System.Random(Program.CarCount).Next(0, 500000);
Program.CarCount++;
}
public Car CreateWheels()
{
// Adds Wheel 2 Car
}
}
public class Wheel
{
public Int64? Id { get; set; }
public string Manufacturer { get; set; } = "Continental";
public Wheel() { Id = Program.WheelCount; }
}
Unfortunately as it is a test project for a different project I'm working on I'm not able to split up the raw-data into multiple OR-tables.
To work with a single table instead I flatten them into a single CarDto class that matches my single db table.
I flatten both classes into the CarDto to be used with LINQ 2 SQLite using AutoMap and assigning the individual db columns.
[Table(Name = "Cars")]
[AutoMap(typeof(Car), ReverseMap = true)]
public class CarDto
{
public CarDto(){ }
[Column(IsPrimaryKey = true)]
public Int64? Id { get; set; }
[Column]
public string Manufacturer { get; set; }
[Column]
public double Mileage { get; set; }
[Column]
public Int64? WheelId { get; set; }
[Column]
public string WheelManufacturer { get; set; }
}
Mapping between DTO-class and entity-class is done with a mapper CarMapper using AutoMapper v.9x
public class CarMapper
{
public IMapper Map => Config.CreateMapper();
IConfigurationProvider Config;
public CarMapper()
{
Config = new MapperConfiguration(cfg =>
{
cfg.AddMaps(typeof(CarMapper).Assembly);
});
Config.AssertConfigurationIsValid();
}
}
Interaction with the db is handled via a repository class CarRepocontaining the mapper and the DataContext class of C# Linq2SQL
public class CarContext : DataContext
{
public Table<CarDto> CarDtos;
public CarContext(IDbConnection connection) : base(connection) { }
}
public class CarRepo
{
private string conn;
CarMapper mp = new CarMapper();
CarContext CarContext => new CarContext(new SQLiteConnection(conn));
public IQueryable<Car> Cars { get => Qry(); }
public CarRepo(string connectionString) { this.conn = connectionString; }
private IQueryable<Car> Qry()
{
return mp.Map.ProjectTo<Car>(CarContext.CarDtos);
}
public List<Car> GetAllCarsFromDb()
{
var dtosFromDb = new List<CarDto>();
using (var db = CarContext)
return mp.Map.Map<List<CarDto>, List<Car>>(db.CarDtos.ToList());
}
public void InsertCars(List<Car> cars)
{
using (var db = CarContext)
{
db.CarDtos.InsertAllOnSubmit(mp.Map.Map<List<Car>, List<CarDto>>(cars));
db.SubmitChanges();
}
}
}
The problem:
Insertion and mapping the CarDto-table to Car works flawlessly. Running repo.Cars.Where(car => car.Id <= 5).ToList(); results as expected except for the nested object Wheel, which always returns as null. The problem exists when projecting a car-query and probably lies in the mapping of the query expression. Looking at the resulting query this seems obvious.
SELECT[t0].[Id], [t0].[Manufacturer], [t0].[Mileage]
FROM[Cars] AS[t0]
WHERE[t0].[Id] <= @p0
Running the following mapping mp.Map.Map<List<CarDto>, List<Car>>(db.CarDtos.ToList()); works and delivers Car including Wheel instances.
I tried loads of solutions (custom mappings,... ) and went through the AutoMapper documentation but wasn't able to fix my problem. Hope someone can help me.
Cheers from germany! Henrik
EDIT: P.s. I added a gist https://gitlab.com/snippets/1957648 https://gist.github.com/henrikherr/29eb2913d403ab1d6bede52ed011869a