Multidimensional navigational properties in Entity Framework 6 Code First - c#

I am trying to figure out if something like this this possible:
Suppose I have the following model of a sports team:
Person( ID, Name, Roles)
Role ( Person, Title) ex: Owner, Player, Coach, ... a Person can have more than one role ( A player can be an owner for example)
Now lets say that I want to create a team Model something like this:
public class Team {
public string Name {get; set; }
public virtual Dictionary<Role, List<Person>> TeamMemebers {get; set; }
}
vs doing something like this:
public class Team {
public string Name {get; set; }
public virtual List<Person>> Players {get; set; }
public virtual List<Person>> Owners {get; set; }
public virtual List<Person>> Coaches {get; set; }
...
}
I am trying to figure out if this is possible?
Thanks

If you need only select on this property then I would create one partial class for model (as in your 2nd snippet) and another one for custom methods and properties.
And there I would add
[System.ComponentModel.DataAnnotations.Schema.NotMapped]
Dictionary<Role, List<Person>> TeamMemebers
{
get
{
// return select mapped to dictionary
}
}

Related

NET Mvc add to list a different instances objects from another model

I've started to learn .NET mvc and I've been struggling with this for a while.
The below code was simplified just to show the problem.
I have a model with a class like this, which includes a list of dogs:
public class Animals {
public long id {get; set;}
public List<Dog> Dogs {get; set;}
}
I have another model called Dog, with instances of each breed, which I constructed like this:
public class Dog
{
public Puddle Puddle {get; set;}
public Retriver Retriver {get; set;}
public Terrier Terrier {get; set;}
}
public class Puddle {
public string Name {get; set;}
public DateTime DayOfBirth {get; set;}
}
public class Retriver {
public string Name {get; set;}
public int Age {get; set;}
}
public class Terrier {
public string color {get; set;}
}
My aim is to create a list of dogs under the Animal object. In other words, add a dog object to a list, depending on what breed a user will choose in the view.
My controller:
public ActionResult AddDog(long id, string breed, DateTime date)
{
var animal = db.Animals.Find(id);
if (animal == null) return HttpNotFound();
if (breed == "puddle")
{
Dog<Puddle> newPuddle = new Dog<Puddle>()
{
DayOfBirth = date
};
animal.Dogs.Add(newPuddle );
db.SaveChanges();
}
return View();
}
Each breed will have a different properties. I want a single list of different type of dogs under Animal object.
In the above controller, of course I cannot use Puddle as a type argument, but I'm not sure how to resolve this. Please don't be harsh with me.
Your question doesn't really make sense. Why does a Dog have three other dogs as properties?
Are you trying to create a Dog "superclass" that can be inherited to provide more specific types of dogs? If so, then Puddle (should that be Poodle?) would not be standalone classes, but would inherit from Dog. For example...
public class Dog {
public string Id { get; set; }
public string Name { get; set; }
}
public class Terrier : Dog {
public string Color { get; set; }
}
Terrier will now have the properties from Dog, such as Id and Name, as well as the terrier-specific Color.
If that's not what you're trying to do, then please clarify your question.

Entity Framework code first for object with collection of properties

I'm using C# and .NET Core with MySql and Entity Framework.
I have an object with a collection of properties. Like this:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<Property> Properties { get; set; }
}
public class Property
{
public int Id { get; set; }
public string Name { get; set; }
public object Value { get; set; }
}
In this case in the database, I should have tables Products, Properties (where property is described, like name and some additional info), and link table ProductProperties, storing product Id, property Id and Value.
But I can't figure out how to do this with a code-first approach.
How could I implement it with code first?
Is it a good way to create one more entity PropertyValue and store it under Product?
Something like this should give you a 1-to-many relationship, although you need to give Value a type, like string to store it in the database, often for dynamic solutions like this you would then maybe add a type to specify the type to deserialize into, but since you then deserialize anyway you could also just add things as json or something else in the db.
public class Product
{
public int Id {get; set;}
public string Name{get; set;}
public ICollection<Property> Properties{get; set;}
}
public class Property
{
public int Id {get; set;}
public string Name {get; set;}
public string Value {get; set;}
public int ProductId {get; set;}
}
Unless you are making a very dynamic system, it doesn't seem right to have the properties as a table, depends a lot of what you are making, and maybe key-value db might be a better tool for the job if thats what your main problem is, as with most complicated things, it depends.
This example is a convention based approach, which is why properties like ProductId have to be called exactly that. You can look at EntityTypeConfigurations if you want more control of names and relationships and such, or use data annotations to achieve the same job.
Ok so create a table like this:
public class ProductProprties
{
public int ProductId {get; set;}
public Product Product {get;set;}
public int PropertyId {get; set;}
public Property Property {get;set;}
//other props
}
If you are using EntityFramework Core, then you have to add this to your databse context as well:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProdcutProprties>().HasKey(x => new { x.ProductId , x.PropertyId });
}

How to populate nested object in model?

I'm creating a database first web api using entity framework. I created my models by creating ADO.NET Entity Models that were populated automatically with the fields on the tables that I selected. I want to be able to take some of those fields and group them in a custom object so when the xml is displayed, they are displayed as a child node.
An example is if I had the class with the following attributes
public class Person
{
public string firstname{get; set;}
public string lastname{get; set;}
public string street{get; set;}
public string city{get; set;}
public string zip{get; set;}
}
I want it to be something like this instead
public class Person
{
public string firstname{get; set;}
public string lastname{get; set;}
public string address{get; set;}//where address contains street, city, and zip
}
How would I go about in implementing this new Person class and populating the data of the custom object with my dbcontext
It is impossible to change three string properties to the one string property. How you can divide Address property to the street city and zip for example in case when street has two words?
You can create Address class (with three properties) and use it your Person class. But you will have problems when you try to regenerate/update your model - in such case is better to use code first approach.
Belongs-to Relationship
I think what you're looking for is a relationship between Person and a new class called Address.
To reference your new Address class inside Person, you would do the following:
public class Person
{
...
public Guid AddressId { get; set; }
public Address { get; set; }
}
Entity Framework will then associate an Address with the given AddressId with a Person.
Inside Address you can do something like this:
public class Address
{
public string City { get; set; }
public string Street { get; set; }
...
}
Eager Loading
To make sure an Address is loaded when a Person is loaded, you can use Entity Framework's Eager Loading capabilities, such as:
context.Person.Include(x => x.Address)
Use enumerable List like
public class Person
{
public string firstname{get; set;}
public string lastname{get; set;}
public List addresses{ get; set; }
}
public class Address
{
public string street{get; set;}
public string city{get; set;}
public string zip{get; set;}
}

create entity with reference to another existing object

public class Link
{
public virtual Category Category { get; set; }
}
public class Category
{
public Category(){Links = new List<Link>}
public virtual IList<Link> Links {get; set;}
}
My problem is when I wanna create Link with reference to Category I got a error with foreign key.
I try to use fluent api, get threw repo category but still the same problem.
EF want to create new object of Category.
To pass data I get to controller second repo(category) and pass to viewbag data.
4 hours spent to find solution but still I've got nothing, could someone explain it to me how it work that I cant pass that :/
Both of your classes need properties that can be mapped to primary keys. This is most commonly done with an int called ID...
public class Link
{
public int ID { get; set; }
public virtual Category Category { get; set; }
}
public class Category
{
public int ID { get; set; }
public Category(){Links = new List<Link>}
public virtual IList<Link> Links {get; set;}
}

EF TPT Creating and Reading

I have an order class with has a collection of products...
public class Order
{
int id { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public abstract class Product
{
int id { get; set; }
}
Derived from product, I have several different types of product...
public class ProductA : Product
{
public string CustomFieldA {get; set;}
}
public class ProductB : Product
{
public string CustomFieldB {get; set;}
}
I can add these derived products to the order and save them to the database...
var producta = new ProductA();
producta.CustomFieldA = "abc";
order.Products.Add(product);
order.SaveChanges();
This updates the database correctly.
What I can't then figure out is how I access this data!
Order.Products just contains the base class, how can I check which type of derived class each record in Order.Products is and access, for example, CustomFieldA of any that are ProductA.
I suspect either I'm missing something really obvious, or I've done the first part completely wrong!

Categories

Resources