PetaPoco to return self-referencing hierarchy - petapoco

How would one write a query/method to return a POCO that is from a self-referencing database as shown in this question

Firstly you would map it a flat class. eg. db.Fetch<CategoryDb>("select * from categories");
public class CategoryDb {
public int Id { get; set; }
public string Name { get; set; }
public int ParentCategoryId { get; set; }
}
From here I would then create a new Object that self referenced itself. (You could use the existing object with the ParentCategory having the [Result] attribute on it.)
public class Category {
public int Id { get; set; }
public string Name { get; set; }
public Category ParentCategory { get; set; }
}
You could then take this and convert your flat list into a nested list.
I do have code somewhere that can do this, and for which it also provides searching methods etc, but its not on this computer. I will update tomorrow with a link to the code.

Related

Entity Framework - Relationship confusion

I'm having problems understanding Entity Framework Code Firsts relationship creation, as I'm more used to the traditional way.
The one-to-many relationship seems clear to me: The childs only need a foreignKey ID property indicating to which Parent they belong.
public class Parent
{
public int Id { get; set; }
public virtual ICollection<Child> Childs { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public virtual Parent Parent { get; set; }
}
Now, I'm not quite sure how to properly create a many-to-many relationship. Probably, there is an additional table ParentChild necessary, so there is no need for (foreign-key) ID properties right?
public class Parent
{
public int Id { get; set; }
public virtual ICollection<Child> Childs { get; set; }
}
public class Child
{
public int Id { get; set; }
public virtual ICollection<Parent> Parents { get; set; }
}
Now, for the one-to-one relationship, I have no clue.
public class Parent
{
public int Id { get; set; }
public int ChildID { get; set; }
public virtual Child child { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public virtual Parent Parent { get; set; }
}
Are the foreign ID properties even needed or can I just have a Child property in the Parent class and a Parent-type property in the Child Class? And is the virtual keyword allowed when I ommit the foreign key ID properties?
I suggest you to have a look in the entity framework fluent api. One to one relation can be easily achieved with the fluent api. Explanation source. For fast reference:
public class Student
{
public Student() { }
public int StudentId { get; set; }
[Required]
public string StudentName { get; set; }
[Required]
public virtual StudentAddress StudentAddress { get; set; }
}
public class StudentAddress
{
[Key, ForeignKey("Student")]
public int StudentId { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int Zipcode { get; set; }
public string State { get; set; }
public string Country { get; set; }
public virtual Student Student { get; set; }
}
You can override OnModelCreating in your datacontext class.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<StudentAddress>()
.HasKey(e => e.StudentId);
modelBuilder.Entity<StudentAddress>()
.Property(e => e.StudentId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<StudentAddress>()
.HasRequired(e => e.Student)
.WithRequiredDependent(s => s.StudentAddress);
base.OnModelCreating(modelBuilder);
}
With Entity Framework, you don't even have to specify the foreign key relations as it will deduce it from your model and create the tables accordingly. The only relation type you actually have to do something for is the 0..1 or 1 to 0..1 or 1.
Don't forget that the object model is way more permissive than the database model. You can have a property storing a collection in an object but not in a table.
You have to think differently as EF will do the work for you at the databse level and you will have access to all properties defines in your object model, even collection properties.
The rules I always use to get it done is the following :
If the cardinality of the relation is 0..1 or 1, use a reference to the other entity object as your property. If the cardinality is many, use a collection.
Here are some use cases :
1 to Many (many childs per parent) :
public class Parent
{
public int Id { get; set; }
// Navigation property
public virtual ICollection<Child> Childs { get; set; }
}
public class Child
{
public int Id { get; set; }
// Navigation property
public virtual Parent Parent { get; set; }
}
The result in the database would be a Table Parent with a single property (Id) and a table Child with two properties, the Id and the foreign key property automatically generated named Parent_Id (Table name then underscore, then the key property of the related class).
The Many to Many :
public class ClassA
{
public int Id { get; set; }
// Navigation property
public virtual ICollection<ClassB> ClassBs { get; set; }
}
public class ClassB
{
public int Id { get; set; }
// Navigation property
public virtual ICollection<ClassA> ClassAs { get; set; }
}
The result in the database would be a Table ClassA with a single property (Id), a table ClassB with a single property (Id) and a third table (the relation table for the many-to-many relation) with two properties (this Ids of both tables).
EF will deduce what it needs to in order to do the job so you don't have to be more specific then that.
Now for the only somewhat problematic one, the 1 to 1 :
public class ClassA
{
public int Id { get; set; }
// Navigation property
public virtual ClassB ClassB { get; set; }
}
public class ClassB
{
public int Id { get; set; }
// Navigation property
public virtual ClassA ClassA { get; set; }
}
Following the rule I gave at the beginning, this is what we would do. But in this case, EF has no way to know the direction of the relation... A 1-to-1 coule be either direction. We will have to let it know the direction using annotation (to me the easiest way compared to Fluent API).
public class ClassA
{
public int Id { get; set; }
// Navigation property
public virtual ClassB ClassB { get; set; }
}
public class ClassB
{
[ForeignKey("ClassA")]
public int Id { get; set; }
// Navigation property
public virtual ClassA ClassA { get; set; }
}
The annotation [ForeignKey("ClassA")], in ClassB tells EF to use the Id column from ClassB as the foreign key in ClassA.
The result in the database would be a Table ClassA with 2 properties (Id and ClassB_Id) and a table ClassB with a single property (Id).
You don't have to create the foreigh key properties yourself as EF will do it for you.

Is there a method to choose only some specific fields of a table using Automapper or EntityFramework?

I have a table in SqlServerDatabase. Table name is User(Id,Name,Paswd) and Im using automapper in Mvc4. Now i want only specific fields or 2 fields from the table instead of whole table, using automapper.how to do??
basically if the 2 objects have the same fields as in the little example
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Paswd { get; set; }
}
public class UserDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Paswd { get; set; }
}
You just have to ignore the field
Mapper.CreateMap<User, UserDto>()
.ForMember(o => o.Paswd, m => m.Ignore());
You can find a lot of usefull example and features here
Automapepr Wiki

One View for multiple models?

If you need to create one View from various entity (models), is it best to create a separate class as a ViewModel containing the specific properties that you need or is it better to create another entity with the specific properties and associate that entity with the rest of the entities in the ORM designer?
You can merge any number of models into one model by declaring them a property of the main m odel. Suppose that you have the following models:
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public int SchoolID { get; set; }
public virtual School StudentSchool { get; set; }
}
public class School
{
public School()
{
this.Students = new HashSet<Student>();
}
public int SchoolID { get; set; }
public string ASchoolName { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
If you just set the Student class as your view model, you can retrive the School of your student and in this case you doesn't need to do anything.
However we suppose that you also need all schools and all students in your view as your view model. To do this, create another class and add the above classes as its properties:
public class MyModel
{
List<Student> MyStudents { get; set; }
List<School> MySchools { get; set; }
}
You can create any complex model you need by this approach...

MVC4 how to load related data without Navigation Properties

I an fairly new to MVC, and have created an MVC4 application using EF-database-first. The database does not contain foreign key definitions and I can't add them (I don't own the database). Here are two example classes from the database:
public partial class Allocation
{
public int AllocID { get; set; }
public int DeptID { get; set; }
public decimal AllocationPercent { get; set; }
}
public partial class Department
{
public int DeptID { get; set; }
public string DeptName { get; set; }
public string Account { get; set; }
}
The default Allocation Index page shows the department ID. I want to show the department name instead. How can I do this without navigation properties?
I tried
public class AllocationController : Controller
{
private Entities db = new Entities();
//
// GET: /Allocation/
public ActionResult Index()
{
return View(db.Allocation.Include(d => d.DeptID).ToList());
}
...
but this gives an error ("A specified Include path is not valid. The EntityType 'TESTModel.Allocation' does not declare a navigation property with the name 'DeptID'.")...
I'm not sure how to code eager-loading or explicit-loading without navigation properties either, which prompted this question. Efficiency-wise, I don't believe it matters which way I load the related information, so any help in any direction would be appreciated.
The database does not have to have definitions, as long as the fields are there and the entities have been placed in the database with referential integrity in mind. All you need to do is let entity framework know about the relationship. This is done with the virtual keyword to create "Navigational Properties".
public partial class Allocation
{
public int AllocID { get; set; }
public int DeptID { get; set; }
public decimal AllocationPercent { get; set; }
public virtual Department Department { get; set; } /* this is your nav property */
}
public partial class Department
{
public int DeptID { get; set; }
public string DeptName { get; set; }
public string Account { get; set; }
}
Now you can do:
db.Allocation.Include(a => a.Department).ToList()
There may be an error which requires you to use a foreign key definition (although I do not think so). If this is the case, you will need to decorate your navigation property like this
[ForeignKey("DeptID")]
public virtual Department Department { get; set; }
You may also try it this way:
public int AllocID { get; set; }
[ForeignKey("Department")]
public int DeptID { get; set; }
public decimal AllocationPercent { get; set; }
public virtual Department Department { get; set; }
With navigation properties, Travis J's answer is what you need.
If you don't want to use navigation properties, assuming your DB context has a set called Departments, you could do smth like this:
var deptId = db.Allocation.DeptID;
var departments = db.Departments.Where(p => p.DeptID == deptId);
return View(departments.ToList());

DbDataController in MVC4 UpdateEntity failing

I have a datamodel like
ModelA which contains a Collection.
ModelB contains a Collection as a backreference. That is failing because of cyclic references if I query with Include("ModelB"). Not good but I solved that via setting ModelB.List=null for each element.
The problem now is submitting a changed ModelA tree: I am adding ModelB-entities to ModelA.ModelB[]. Now the UpdateEntity function is complaining the it could not add elements of type ModelB which are declared static. The JSON deserializer is creating static arrays.
How is it possible with the combination of upshot/MVC4 to submit datamodels which are not completely flat? As it is not possible right now to create your own DTO objects where you might figure out something I am stuck now...
After investigating the error a bit better, I think the problem is the cyclic backreference:
The ModelA->ModelB->ModelA is breaking the storage of the data. "Could not add data of type ModelA to type ModelB".
As I mentioned the backreference was set to Null because the cyclic ref serialisation problem...
I hope the will be some easier way on doing more manually with DTO objects where I have mroe control.
Please see also: MVC 4, Upshot entities cyclic references for the beginning of the journey...
To solve the cyclic backreference, you can use the ignoreDataMember attribute:
public class Customer
{
[Key]
public int CustomerId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public virtual ICollection<Delivery> Deliveries { get; set; }
}
public class Delivery
{
[Key]
public int DeliveryId { get; set; }
public string Description { get; set; }
public bool IsDelivered { get; set; }
[IgnoreDataMember]
public virtual Customer Customer { get; set; }
public virtual int CustomerId { get; set; }
}
I posted a working solution to your problem in a different question: https://stackoverflow.com/a/10010695/1226140