EF4.1 How to map properties to columns - entity-framework-4.1

Assume I have this class:
class MyDataStore
{
public Guid Id { get; set; }
public int DataStoreType { get; set; }
public Name { get; set; }
public List<string> ExtendedProperties { get; set; }
}
I have the following tables in my DB:
MyDataStore
Id Name DataStoreType
-----------------------------------------
someguid1 ABC 1
MyDataStoreExtended
DataStoreId Property1 Property2
----------------------------------------
someguid1 value1 value2
Another table stores what extended properties my "MyDataStore" has:
MyDataStoreMetadata
Property DataStoreType
-------------------------------------------
Property1 1
Property2 1
Property3 2
Property4 2
Property5 2
Now what are different ways I can map this data schema to my "MyDataStoreClass" using EF 4.1 code-first?
Note: I do not want to delcare "MyDataStoreExtended" class as my POCO, just want to use it for storing data.

Depending on where you are using it, you could wrap MyDataStore in MyDataStoreExtended:
class MyDataStoreExtended
{
public MyDataStore MyDataStore { get; set; }
public int DataStoreId { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
}

Related

Mapping table is empty

Below are two tables that has a many to many relation and and also another table that has a relation with the two first. A mapping table is created by Visual Studio with the name OrderEmployee, but when I run the application and enter some information to the Timeunit create form, the mapping table OrderEmployee is empty!
Should there not be some IDs added to that table since it has a relation with the Timeunit table or how is this mapping table thing working, when will there be data added to the mapping table? Or is something wrong with my Entity Classes?
public class Order
{
public int ID { get; set; }
public string Name { get; set; }
public int? ManufacturerID { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public int EmployeeNumber { get; set; }
public virtual ICollection<Timeunit> Timeunits { get; set; }
public virtual ICollection<Order> Order { get; set; }
}
public class Timeunit
{
public int ID { get; set; }
public int Week { get; set; }
public int HoursPerWeek { get; set; }
public int EmployeeID { get; set; }
public int? OrderID { get; set; }
public virtual Employee Employee { get; set; }
public virtual Order Order { get; set; }
}
EDIT:
Create Method for Timeunit:
public ActionResult Create([Bind(Include = "ID,Week,HoursPerWeek,EmployeeID,OrderID")] Timeunit timeunit)
{
if (ModelState.IsValid)
{
db.Timeunits.Add(timeunit);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ProjectID = new SelectList(db.Orders, "ID", "Name", timeunit.OrderID);
ViewBag.ResourceID = new SelectList(db.Employees, "ID", "Name", timeunit.EmployeeID);
return View(timeunit);
}

How to limit data in a mobile API using EF and WebAPI/JSON

I am writing a PhoneGap/Web/JS mobile application that uses the WebAPI and Entity Framework in the backend.
I have a class called Thing which references the User table 4 times (ChangedByUserId, CreatedByUserId etc. The User table is really large (30 user-related fields)
I want to pass as little data over each call as possible, but I need the User's Name for each of these UserID foreign keys. (this is the only information from the user record I need).
When I use the object graph in EF it returns the FULL user record for each foreign key, so a single Thing object becomes massively bloated. I don't want to make multiple calls to get the Thing POCO object and then the User's name by UserID.
What I really want to do is a sort of flattened DTO object which is just the Thing class below but with a string for each user name, e.g. CreatedByUserName, ChangedByUserName etc. Then I would return this DTO as my hydrated POCO object and the data would be small.
So my question is: How do I do this using Entity Framework? (limit related record's return data?)
public partial class Thing
{
public int ThingId { get; set; }
public int FromUserId { get; set; }
public int ToUserId { get; set; }
public string ThingText { get; set; }
public int StatusId { get; set; }
public int ChangedByUserId { get; set; }
public int CreatedByUserId { get; set; }
public virtual User FromUser { get; set; }
public virtual User ToUser { get; set; }
public virtual User CreatedByUser { get; set; }
public virtual User ChangedByUser { get; set; }
}
As you said, you need to flatten Thing
public class FlatThing
{
public int ThingId { get; set; }
public int FromUserId { get; set; }
public int ToUserId { get; set; }
public string ThingText { get; set; }
public int StatusId { get; set; }
public int ChangedByUserId { get; set; }
public int CreatedByUserId { get; set; }
public string FromUserName { get; set; }
public string ToUserName{ get; set; }
}
// assume you have your things
var flatThings = new List<FlatThings>;
foreach (Thing t in things)
flatThings.Add(new FlatThing{ ThingId = t.ThingId, FromUserId = t.FromUserId,
FromUserName = t.FromUser.Name .....});
return flatThings;

Composite Keys in EF 4.2 Code First

I have the following Classes and am using EF 4.2 Code First
public class PartAttribute
{
public Part Part { get; set; }
public PartAttributeType PartAttributeType { get; set; }
[Timestamp]
public byte[] Time { get; set; }
[Required]
public string Value { get; set; }
}
public class Part
{
public Guid Id { get; set; }
[Required]
public PartType PartType { get; set; }
[Required]
public string SerialNumber { get; set; }
public string Description { get; set; }
public ICollection<Team> SelectedTeams { get; set; }
}
public class PartAttributeType
{
public Guid Id { get; set; }
[Required]
public PartType PartType { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
}
When I build my model it creates the three tables and the relationships between the tables as I would like/expect them. I am trying to create a composite key on the PartAttribute table between the Part, PartAttributeType, and the time and I can't seem to figure it out. When I try to add
modelBuilder.Entity<PartAttribute>().HasKey(c => new { c.Part, c.PartAttributeType, c.Time });
I get an error saying Part is not a scalar type (which it is not).
You need to introduce foreign key properties which can act as primary keys at the same time:
public class PartAttribute
{
public Guid PartId { get; set; }
public Guid PartAttributeTypeId { get; set; }
public Part Part { get; set; }
public PartAttributeType PartAttributeType { get; set; }
[Timestamp]
public byte[] Time { get; set; }
[Required]
public string Value { get; set; }
}
Then your mapping:
modelBuilder.Entity<PartAttribute>()
.HasKey(c => new { c.PartId, c.PartAttributeTypeId, c.Time });
EF should be able to recognize the new properties as the foreign keys for your two navigation properties due to the naming convention.

Code First with an existing database

I have a table in database which points to itself, i.e. parent_id >> category id. This is the ER diagram
I have modelled this table like following, but it gives *Error : 'Category': member names cannot be the same as their enclosing type :
public class Category
{
[Key]
public int category_id { get; set; }
public string category_name { get; set; }
public int category_parent { get; set; }
public string category_desc { get; set; }
public virtual Category Category { get; set; }
}
How should I model such tables ?
You have to make category_parent nullable and configure navigational property Category to the scalar property category_parent. Try to use proper naming convensions.
public class Category
{
[Key]
[Column("category_id")]
public int Id { get; set; }
[Column("category_name")]
public string Name { get; set; }
[Column("category_parent")]
public int? ParentId { get; set; }
[Column("category_desc")]
public string Description { get; set; }
[ForeignKey("ParentId")]
public virtual Category ParentCategory { get; set; }
}
I think you just need to change the Category property name to something else, so it is not the same as the class name...
public virtual Category SubCategory { get; set; }
public class Category
{
[Key]
public int category_id { get; set; }
public string category_name { get; set; }
public int category_parent { get; set; }
public string category_desc { get; set; }
public int parent_category_id { get; set; } <-- ADD & setup as foreign key
public virtual Category ParentCategory { get; set; } <-- Change name
public virtual ICollection<Category> Categories { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Category>.HasMany(cat => cat.Categories)
.WithRequired()
.HasForeignKey(cat => cat.parent_category_id);
}

Creating BiDirectional One - One relationship in Entity Framework 4.1 Code First

I want to created Bi-Directional One-One relationship between two entities using EF Code First. I have trouble with the following code. What do you think I should do?
public class User
{
public string ID { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public int ProfileID { get; set; }
public Profile Profile { get; set; }
}
public class Profile
{
public int UserID { get; set; }
public User User { get; set; }
public int ProfileID { get; set; }
public string ProfileName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
}
I want to have both Navigation property and Foreign Key in both the entities.
This gives me error. What can do I in Fluent Mapping API to make this work?
Use this:
public class User
{
public string ID { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public Profile Profile { get; set; }
}
public class Profile
{
[Key, ForeignKey("User")]
public int ProfileID { get; set; }
public string ProfileName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
public User User { get; set; }
}
That is the only valid way to build one-to-one relation in EF - PK of the dependent entity must be also FK to principal entity. There is nothing like bidirectional one-to-one relation in EF because it cannot work in EF.
The way how people sometimes overcome this are two one-to-many relations where principal doesn't have navigation collection for dependent entities + manually defined unique keys in the database. That require manual mapping:
public class User
{
public string ID { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
// one side MUST be nullable otherwise you have bidirectional constraint where each
// entity demands other side to be inserted first = not possible
public int? ProfileId { get; set; }
public Profile Profile { get; set; }
}
public class Profile
{
public int ProfileID { get; set; }
public string ProfileName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
And in mapping you will define:
modelBuilder.Entity<User>
.HasOptional(u => u.Profile)
.WithMany()
.HasForeignKey(u => u.ProfileId);
modelBuilder.Entity<Profile>
.HasRequired(u => u.User)
.WithMany()
.HasForeignKey(u => u.UserId);
Now you must define Unique keys in the database - if you are using code first use custom database initializer. Be aware that still bidirectional one-to-one is wrong concept because both sides demand unique FK where NULL is still included in unique values so once you insert User before Profile there mustn't be any other User without Profile. That probably leads to serializable transaction.