EF 4.1 Code First doesn't create column for List<string> - entity-framework-4.1

I have been playing around quite a lot with EF4 Code First and I do love it. However, I cannot seem to sort this easy one out.
When trying to create something like this, no columns are created in my database:
public IList<String> Recievers { get; set; }
public List<String> RecieversTest { get; set; }
public virtual List<String> RecieversAnotherTest { get; set; }
public virtual ICollection<Int32> RecieversAnotherTest { get; set; }
Ive tried Annotations to map it to a different column name, I've tried IEnumerable and all sorts of other collections, but it refuses to create a column for it.
After an hour on google I found one that claims she has done it, but I'm starting to doubt that. Should it even be possible?
I can't really see why it just doesn't create a column and use JSON or CSV.
It can't be that rare, can it? In my case i just want to store a list of emails.
What am I missing? The project creates all other types without problems, and I've inspected the database to see how other properties I add to test with gets created, while these gets ignored.
So the problem must lie in some setting I'm missing or some configuration....
EF 4.1 RTW on an SQL Server 2008 db.

I have bad news for you. EF doesn't do anything like that. If you want any serialization and deserialization you must do it yourselves = you must expose and map property with serialized value:
private IList<String> _receivers;
// This will be skipped
public IList<String> Receivers
{
get
{
return _receivers;
}
set
{
_receivers = value;
}
}
// This will be mapped
public string ReceiversSer
{
get
{
return String.Join(";", _receivers);
}
set
{
_receivers = value.Split(';').ToList();
}
}
Now ReceiversSer will be mapped to a column in the database.

You can't have a column based on a collection/list of something. A column is a singular item such as public string Receiver.
If you are expecting EF CF to take your IList or List and make several Columns out of it you are correct in that it won't.
In EF CF you create lists in your Entity to represent a relationship to another table. An Order may have many Items in it. You would in this case have an Order class with a list to an OrderItem object.
You would then have an OrderItem class to describe the OrderItem table. This would then essentially represent the 1 to many relationship of Order and OrderItems.

Related

Unknown Column In Field List - Field Does Not Exist on Entity

I'm having an issue figuring out where Entity Framework is getting the list of column names to query from a MySQL database. Essentially, when I am querying my context for a list of Discounts, a seemingly random property is getting attached, which doesn't exist in the database. I can't seem to find where, so I'm hoping someone has some troubleshooting guidance for me.
I have a Discount entity, that inherits off of my 'EntityBase' class.
public class Discount : EntityBase
{
public Discount(){}
}
public class EntityBase
{
public int Id { get; set; }
}
When I attempt to query discounts...
var discount = _myContext.Discounts.FirstOrDefault();
I get the following error - Unknown column 'd.AttendeeBadgeId' in 'field list'
Now, I DO have an AttendeeBadge entity, and I have a variety of other entities that utilize the AttendeeBadge. But I have absolutely nothing in the Discount class that utilizes the AttendeeBadge entity. I just have the Id property that gets inherited through EntityBase - and yet, my generated MySQL query is...
SELECT `d`.`Id`, `d`.`AttendeeBadgeId`
FROM `Discount` AS `d`
LIMIT 1
I've validated that in my modelBuilder for my context, I'm not mapping any particular properties that would cause an issue.
modelBuilder.Entity<Discount>().ToTable("Discount");
modelBuilder.Entity<Discount>().HasKey(_ => _.Id);
I thought something might be cached, but I've deleted all of the bin/obj folders for every single project in my solution, and I used Notepad++ to validate all of the areas that I reference the string value "AttendeeBadgeId", and I just get the other classes that reference it.
I'm at a loss here, would anyone know how I could see how the context is generating the SQL query in a more verbose way, or see where that column is coming from?
I should have tried harder before posting.
It turns out I had a property on the AttendeeBadge entity that had a list of Discounts.
public class AttendeeBadge : EntityBase
{
public AttendeeBadge ()
{
Discounts = new HashSet<Discount>();
}
public ICollection<Discount> Discounts { get; set; }
}
This was causing Entity Framework to assume there was a relationship between the Discount and the AttendeeBadge when I removed that dependency earlier today. I found out by copying the Discount class to another class, and then re-mapping my entities until I found the culprit causing my issue.

Returning a Json-field from SQL to ASP.NET Core API

I'm building a relatively simple Get-method in an ASP.NET Core (3+) application. (Currently 3.1 - to be migrated to 5)
The object I need to return looks like this:
public class Data
{
public int ID { get;set;}
public string Name { get;set;}
public string Settings { get; set;}
}
And the Get-method is simply this:
public IActionResult<Data> GetData()
{
var data = _dbContext.GetData<Data>();
return Ok(data);
}
This works perfectly - except for one thing.
In SQL - the settings column (varchar(8000)), contains JSON data. In some cases, a setting can be something simple like : { "threshold": 8754 } and sometimes it can be a large complex object with many fields, but it is always valid Json.
On the ASP side, it does exactly what you would expect. It turns a serialized Json object that contains an INT and 2 x strings.
I would like for it to return an INT, ONE String and One Json Object.
Is there any way that I can tell the serializer that the Settings-property contains Json?
In a perfect world, I would love something like this:
public class Data
{
public int ID { get;set;}
public string Name { get;set;}
[SerializeContentAsJson]
public string Settings { get; set;}
}
Is there a way to do this or is there some other fairly elegant solution to this problem?
Btw. I fully realize that the caller can specify the content types that he/she will accept. In this case, the API is purely for use inside my team and we will always want JSON, so I can compromise on this being a relatively custom solution that might not work if you wanted text/html or some other content type.

Save DropDownListFor multiple selected values

How can I save data for a multiple DropDownListFor? I have this code but the selected items aren't reaching the controller.
My code view:
#Html.DropDownListFor(model => model.Ingredients, new SelectList(Model.ListIngredients, "Id", "Description"), "Select the ingredients", new { multiple = "multiple", })
My model:
public ICollection<Ingredient> Ingredients { get; set; }
public ICollection<Ingredient> ListIngredients{ get; set; }
Ingredient.cs:
public string Description { get; set; }
public int Id { get; set; }
I have to change the name and id of my helper for data to be saved?
You are trying to bind the selected values into a collection of Ingredients.
However if you take a look at the posted values, they will look something like this:
...Ingredients=1&Ingredients=2...
That means the model binder will not know how to convert values like 1,2 (which are the ingredient Ids) into instances of the ingredient class.
You need to change the property of your view model where you will get the ingredients selected by the user, so instead of a collection of Ingredients:
public ICollection<Ingredient> Ingredients { get; set; }
you have a collection of Ids (which is the property you are using as the value of the multi-select), for example:
public int[] SelectedIngredients { get; set; }
(I have renamed the property but that is not strictly needed, I have done it just for clarity)
As a suggestion, I would remove the default option value from that multi-select (The "Select the ingredients" option) and use a label or tooltip. Otherwise it may look like any other value from the list and you will have to deal with the scenario where the user selects that option, which is not a valid ingredient.
Even better, I would also use the #Model.ListBoxFor helper as that will let everybody know they are dealing with a multi-select. Otherwise (with the drop down helper) you may not realize it is a multi-select unless you look at the attributes. Something like:
#Html.ListBoxFor(m=>m.SelectedIngredients, new SelectList(Model.ListIngredients, "Id", "Description"))
Of course, these are just suggestions. You can happily Ignore them if they don't apply to your requirements!
As a final comment, it is possible to convert the posted values into Ingredient objects as you initially had in your view model. That would require you to write your own model binder and configure it for the Ingredient type. However you will only receive the id in the posted values, so you would have to retrieve the other properties (from the database probably) or you will have a collection of Ingredient objects where only the Id is populated. I would not go down this route unless you really need to.

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.

Linq - How to put common fields in a base class

I am trying to find a way so that I can push some common functionality into a base class for my Linq to SQL processing. I have two fields (ID and InsertUpdateOperID) that are common to most but not all of my tables. In my first go around I created a class called BaseEntity that had these fields. Unfortunately all I accomplished was hiding from the values in the .designer.cs file. I found an example of how to accomplish what I wanted In order to get around this (http://www.joe-stevens.com/2009/07/01/linq-to-sql-set-inheritance-modifiers-with-sqlmetal/). As per this article, I modifed the DBML file so that I could add the override modifier to the ID and InsertUpdateOperID properties on the tables that contained these two fields.
The net result of this was that the .designer.cs file added the override qualifier where I wanted it. This enabled me to create my BaseEntity class. Where I defined the ID field and the InsertUpdateOperID field as:
public virtual int ID { get; set; }
public virtual int InsertUpdateOperID { get; set; }
Doing this seemed to work fine.
The problem for me is that I hate the idea of modifying generated code. Can anyone suggest a way for me to put common fields and methods that act on those common fields in a base class so that I could accomplish what I want without modifying the generated .dbml?
Thanks
I'm facing the same problem today (wow, it's 1.5 years after your post), and struggled out a solution, so far it's good for me.
in the base class:
public virtual int __ID
{
get
{
PropertyInfo pi = this.GetType().GetProperty("ID");
int id = (int)pi.GetValue(this, new object[] {});
return id;
}
set
{
PropertyInfo pi = this.GetType().GetProperty("ID");
pi.SetValue(this, value, new object[] { });
}
}
This looks quite voilent, but it works!
Notice the __ before ID, because there is alread ID and _ID in the auto generated codes. As it's totally a new third way to access ID, no "override" is needed.
And if you need, you can use the __ID in or via your base class.