EF Core 2.1 - Query types support with models - ef-core-2.1

While I use DbQuery, should the columns in the select statement query match exactly same as the model/entity?
Below is the example:
IEnumerable<UserModel> test = _context.FewUserColumns.FromSql(#"select id,
last_name, from user where user_id = #userId",
param).ToListAsync();
Below is the UserModel.
public class userModel
{
public int id {get;set;}
public string first_name { get; set; }
public string last_name { get; set; }
}
I am not fetching first_name in the above select statement. due to this i see the below error.
An unhandled exception occurred while processing the request.
InvalidOperationException: The required column 'first_name' was not present in the results of a 'FromSql' operation.
Is that expected? Should we always fetch all the columns to map to all the properties in the model?

I had posted a similar query on msdn and received a response from Julie Lerman:
Yes, unfortunately that is a constraint...EF Core expects all of those
properties to be available.

Related

Unable to scaffold "date" type columns from MySQL in .net core 2

I've started a new .net core 2 project and I'm trying to import a MySQL database to entity framework.
I use this command to scaffold the DB:
Scaffold-DbContext "server=localhost;port=3306;user id=user;password=pass;database=MyDB;" "Pomelo.EntityFrameworkCore.MySql"
The process is successful, but I get this type of warning for each table that contains date columns:
Could not find type mapping for column
'my_table.DATE_ADDED' with data type 'date'. Skipping
column.
This is the table:
ACCOUNT_ID int(10) UN PK
VIDEO_ID int(10) UN PK
DATE_ADDED date
The model being created is this:
public partial class MyTable
{
public int AccountId { get; set; }
public int VideoId { get; set; }
public Accounts Account { get; set; }
public Videos Video { get; set; }
}
My question is, is there any way to do the scaffolding process that will include date fields? if not, is there any way to fix the model so it can use the date data?

Anonymous object blob in database not serializing as JSON when queried

I have a need to store an unknown data structure in a SQL Server database table field via ORMLite. This is to support a timeline feature on a website where each step on the timeline contains different information, and I want to store them as generic "Steps", with the variable data in a "StepData" property. I have the POCO set up like this:
public class ItemStep
{
public ItemStep()
{
this.Complete = false;
}
[Alias("ItemStepId")]
public Guid Id { get; set; }
[References(typeof(Item))]
public Guid ItemId { get; set; }
[References(typeof(Step))]
public int StepId { get; set; }
public object StepData { get; set; }
[Reference]
public Step Step { get; set; }
public bool Complete { get; set; }
public DateTime? CompletedOn { get; set; }
}
My front-end send a JSON object for StepData, and it's saved to the database appropriately.
{itemAmount:1000,isRed:False,isBlue:True,conversion:True}
Now, when I go to retrieve that data using...
List<ItemStep> itemSteps = Db.Select<ItemStep>(q => q.ItemId == request.ItemId).OrderByDescending(q => q.StepId).ToList<ItemStep>();
...the "StepData" node of the JSON response on the client is not a Javascript Array object as I'm expecting. So, on the client (AngularJS app using Coffeescript),
ItemStep.getItemSteps(ItemId).then((response) ->
$scope.StepData = response.data.itemSteps[0].stepData
is a double-quoted string of the JSON array.
"{itemAmount:1000,isRed:False,isBlue:True,conversion:True}"
Can anybody help me with this? I've tried parsing that string as JSON and I can't seem to get it to work:
JSON.parse($scope.StepData)
I'm using the exact same methodology in other areas of the app to store and retrieve things like addresses, with the only difference I can see being that there is a specified Address class.
Thanks!
Found this link that solved my problem: https://github.com/ServiceStackV3/mythz_blog/blob/master/pages/314.md
Essentially I added a "Type" field to the ItemStep class, and set that when I create a new row (create the next step in the timeline). Then, when I retrieve that record, I call a method like "GetBody" in the referenced link (GetStepData for me), that deserializes the object using the stored Type. I then stuff that back into a generic "object" type in the return POCO so that I can include many steps of varying types in the same call. Works great!
Thanks Mythz for the blog post!

After saving object using Entity Framework to MySQL the object id still shows as 0

I am using Entity Framework and have a connection to a MySQL database. The id column is set to use StoreGeneratedPattern Identity and the column in the database has been set to auto-increment. When I create a new object and save it to the database, the item posts correctly in the database. However, after saving, the id of the object in C# remains 0 rather than reflecting the value than was assigned by the database.
The section of code is given below:
Group newGroup = new Group("MyGroupName", "Active");
dbContext.Groups.Add(newGroup);
dbContext.SaveChanges();
int testId = newGroup.id;
Even though "newGroup" saves in the database with a database-assigned id, when I read the id (such as I do when reading testId) the id is still 0.
Based on this, I have tried adding
dbContext.Entry(newGroup).Reload();
after SaveChanges() and I have also tried (based on this and this) adding
var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
objectContext.Refresh(System.Data.Objects.RefreshMode.StoreWins, newGroup);
after SaveChanges() in an attempt to refresh the object (and thus the id) from the database, yet the problem remains. How can I get the id that was assigned by the database?
EDIT: Adding class definition for Group:
[Table("groups")]
public partial class Group
{
public Group()
{
this.user_groups = new HashSet<UserGroup>();
}
public long id { get; set; }
public string name { get; set; }
public string status { get; set; }
public System.DateTime created_at { get; set; }
public System.DateTime updated_at { get; set; }
public virtual ICollection<UserGroup> user_groups { get; set; }
}
Try decorating your id with the [Key] attribute.
It SHOULD be this attribute
[DatabaseGenerated(DatabaseGenerationOption.Identity)]
However, this SHOULD be the default.
The [Key] attribute, should be unnecessary since the column name Id is magical... Although this might only be the case when using the accepted naming convention for C#.
I wonder if it might be the long that your id property is typed, or possibly the naming convention... you could try naming it Id.
I'm having the same problem with my project. What I did for a work around was to order the table (group) by the ID descending and select the first or default record, then select the ID column.
var newID = dbcontext.Groups.OrderByDescending(x => x.id).FirstOrDefault().ID
You can then assign that to whatever you need and save changes again. I know it's an old thread but hopefully this helps. Seems like there should be a better way to do it...

How do I populate a Data Access Layer Model Efficiently?

I'm working on developing my first Data Driven Domain using Dependency Injection in ASP.net.
In my Data Access Layer if have created some domain data models, for example:
public class Company {
public Guid CompanyId { get; set; }
public string Name { get; set; }
}
public class Employee {
public Guid EmployeeId { get; set; }
public Guid CompanyId { get; set; }
public string Name { get; set; }
}
I have then developed an interface such as:
public interface ICompanyService {
IEnumerable<Model.Company> GetCompanies();
IEnumerable<Model.Employee> GetEmployees();
IEnumerable<Model.Employee> GetEmployees(Guid companyId);
}
In a separate module I have implemented this interface using Linq to Sql:
public class CompanyService : ICompanyService {
public IEnumerable<Model.Employee> GetEmployees();
{
return EmployeeDb
.OrderBy(e => e.Name)
.Select(e => e.ToDomainEntity())
.AsEnumerable();
}
}
Where ToDomainEntity() is implemented in the employee repository class as an extension method to the base entity class:
public Model.EmployeeToDomainEntity()
{
return new Model.Employee {
EmployeeId = this.EmployeeId,
CompanyId = this.CompanyId,
Name = this.Name
};
}
To this point, I have more or less followed the patterns as described in Mark Seeman's excellent book 'Dependency Injection in .NET' - and all works nicely.
I would like however to extend my basic models to also include key reference models, so the domain Employee class would become:
public class Employee {
public Guid EmployeeId { get; set; }
public Guid CompanyId { get; set; }
public Company { get; set; }
public string Name { get; set; }
}
and the ToDomainEntity() function would be extended to:
public Model.Employee ToDomainEntity()
{
return new Model.Employee {
EmployeeId = this.EmployeeId,
CompanyId = this.CompanyId,
Company = (this.Company == null) ? null : this.Company.ToDomainEntity()
Name = this.Name
};
}
I suspect that this might be 'bad practice' from a domain modelling point of view, but the problem I have encountered would also, I think, hold true if I were to develop a specific View Model to achieve the same purpose.
In essence, the problem I have run into is the speed/efficiency of populating the data models. If I use the ToDomainEntity() approach described above, Linq to Sql creates a separate SQL call to retrieve the data for each Employee's Company record. This, as you would expect, increases the time taken to evaluate the SQL expression quite considerably (from around 100ms to 7 seconds on our test database), particularly if the data tree is complex (as separate SQL calls are made to populate each node/sub-node of the tree).
If I create the data model 'inline...
public IEnumerable<Model.Employee> GetEmployees();
{
return EmployeeDb
.OrderBy(e => e.Name)
.Select(e => new Model.Employee {
EmployeeId = e.EmployeeId,
/* Other field mappings */
Company = new Model.Company {
CompanyId = e.Company.CompanyId,
/* Other field mappings */
}
}).AsEnumerable();
}
Linq to SQL produces a nice, tight SQL statement that natively uses the 'inner join' method to associate the Company with the Employee.
I have two questions:
1) Is it considered 'bad practice' to reference associated data classes from within a domain class object?
2) If this is the case, and a specific View Model is created for the purpose, what is the right way of populating the model using without having to resort to creating inline assignment blocks to build the expression tree?
Any help/advice would be much appreciated.
The problem is caused by having both data layer entities and domain layer entities and needing a mapping between the two. Although you can get this to work, this makes everything very complex, as you are already experiencing. You are making mappings between data and domain, and will soon add many more mappings for these same entities, because of performance reasons and because other business logic and presentation logic will need different data.
The only real solution is to ditch your data entities and create POCO model objects that can directly be serialized to your backend store (SQL server).
POCO entities is something that is supported in LINQ to SQL from day one, but I think it would be better to migrate to Entity Framework Code First.
When doing this, you can expose IQueryable<T> interfaces from your repositories (you currently called your repository ICompanyService, but a better name would be ICompanyRepository). This allows you to do efficient LINQ queries. When querying directly over a query provider you can prevent loading complete entities. For instance:
from employee in this.repository.GetEmployees()
where employee.Company.Name.StartWith(searchString)
select new
{
employee.Name,
employee.Company.Location
};
When working with IQueryable<T>, LINQ to SQL and Entity Framework will translate this to a very efficient SQL query that only returns the employe name and company location from the database with filtering inside the database (compared to do filtering in your .NET application when GetEmployees() returns an IEnumerable<T>).
You can ask Linq2Sql to preload certain entities (as opposed to lazy load them) using DataLoadOptions.LoadWith method see: http://msdn.microsoft.com/en-us/library/bb534268.aspx.
If you do this with the Company entity then I think Linq2Sql won't have to reach to the database to fetch it again.

Entity Framework 4.1 Fluent mapping Foreign Key and the Foreign object with a string key

I am moving from an EDMX mapping to the EF 4.1 DbContext and Fluent mapping and I am wanting to map both a string foreign key and the foreign object using the fluent API. I have an Employee with an Optional Office. I would like both the OfficeId and the Office Object in the Employee class (This is all read only, and I do not need to be able to save these objects). Objects with int keys work fine, but I have tried several with string keys and get the same result - the OfficeId field populates, but the Office object comes back as null. Chekcking in SQL profiler the data is being queried, but the office object is not being populated.
public partial class Employee
{
public int Id { get; set; }
// snip irrelevant properties
public Office Office { get; set; } // this is (incorrectly) always null
public string OfficeId { get; set; }
public WorkGroup WorkGroup { get; set; } // this one with the int key is fine
public int? WorkGroupId { get; set; }
// snip more properties
}
public partial class Office
{
public string Id { get; set; }
public string Description { get; set; }
}
public partial class WorkGroup
{
public int Id { get; set; }
public string Code { get; set; }
}
After feedback from Ladislav below, I map it like this in the OnModelCreating
modelBuilder.Entity<Employee>().HasKey(d => d.Id).ToTable("Employee", "ExpertQuery");
modelBuilder.Entity<Office>().HasKey(d => d.Id).ToTable("Office", "ExpertQuery");
modelBuilder.Entity<WorkGroup>().HasKey(d => d.Id).ToTable("WorkGroup", "ExpertQuery");
modelBuilder.Entity<Employee>()
.HasOptional(a => a.Office)
.WithMany()
.Map(x => x.MapKey("OfficeId")); // this one does not work
modelBuilder.Entity<Employee>()
.HasOptional(e => e.WorkGroup)
.WithMany()
.HasForeignKey(e => e.WorkGroupId); // this one works fine
I assume there is some subtlety with string keys that I am missing ? I am querying it as follows :
var employees = expertEntities.Employees.Include("Office").Include("WorkGroup").Take(10).ToList();
If I omit the OfficeId field from Employee, and set up the mapping like this :
modelBuilder.Entity<Employee>()
.HasOptional(e => e.BusinessEntity)
.WithMany()
.Map(x => x.MapKey("OfficeId"));
Then the office object is populated, but I need the OfficeId field in the Employee object.
Well, I found the issue - it's a data issue - the primary key string values were space padded and the foreign key values were not (!). Although SQL joins the tables correctly (ignoring the padding) and fetches the correct data, it appears that EF will not correlate it back into the the correct objects as .NET is fussier than SQL about trailing blanks.
Your customized mapping just conflicts because of the fact that you have already introduced a OfficeId property of string type. See what happens if you remove the OfficeId property from your Employee definition, or change it to int type.
That is not correct mapping. If you have FK property you cannot use Map and MapKey. That is for scenarios where you don't have that property. Try this:
modelBuilder.Entity<Employee>()
.HasOptional(a => a.Office)
.WithMany()
.HasForeignKey(a => a.OfficeId);
Also first part of your mapping with mapping entities to table is most probably incorrect. Map is used for inheritance and entity splitting scenarios. You are looking for ToTable:
modelBuilder.Entity<Employee>().HasKey(d => d.Id).ToTable("ExpertQuery.Employee");
Also if your ExpertQuery is database schema and not part of table name it should look like:
modelBuilder.Entity<Employee>().HasKey(d => d.Id).ToTable("Employee", "ExpertQuery");