How to had foreign key - database

(lol).
For who I know I been working (for training) on a pokemon database.
I have a problem with my database creation.
I have 18 different types :
"Acier"
"Combat"
"Dragon"
"Eau"
"Electrik"
"Fee"
"Feu"
"Glace"
"Insecte"
"Normal"
"Plante"
"Poison"
"Psy"
"Roche"
"Sol"
"Spectre"
"Tenebre"
"Vol"
A pokemon can have one OR two types :
Example :
Pickachu type Electrik.
Bulbizarre type Plante and Poison.
I try to use foreign key for create my database but I don't know how to do it please help.
I have a Pokemon model class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace Pokemon.Models
{
[Table("Pokemons")]
public class Pokemon
{
[Key]
public int PokemonId { get; set; }
[StringLength(30)]
public string PokemonName { get; set; }
[StringLength(30)]
public string PokemonUsName { get; set; }
[StringLength(30)]
public string PokemonDeName { get; set; }
[StringLength(30)]
public string PokemonJpName { get; set; }
public string PokemonDescription { get; set; }
public int PokemonRate { get; set; }
public string PokemonImage { get; set; }
public int PokemonTypeId { get; set; }
[ForeignKey("PokemonType")]
public virtual PokemonType PokemonType { get; set; }
}
}
And a PokemonType model class:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace Pokemon.Models
{
[Table("PokemonTypes")]
public class PokemonType
{
[Key]
public int TypeId { get; set; }
[StringLength(8)]
public string Type { get; set; }
public virtual ICollection<Pokemon> Pokemons { get; set; }
}
}
I hope I asked my question clearly.
I want to make a pokemon "Bulbizarre" whit Type1Id = 7 //7for plante
And type2Id = 24 //24 for poison.
But some of them have only one type : type1Id 13 //13 for Electrik
and Type2Id = null. //because no second type.
Table PokemonTypes screen from databse

I made it !
I made databse first and scaffold it!
Database diagram
this make me 3 model class with everythings correct inside
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DataModels.Models
{
public partial class Pokemons
{
public Pokemons()
{
PokemonsPokemonTypes = new HashSet<PokemonsPokemonTypes>();
}
public int Id { get; set; }
public int Num { get; set; }
[Required]
[StringLength(30)]
public string Name { get; set; }
[StringLength(30)]
public string UsName { get; set; }
[StringLength(30)]
public string JpName { get; set; }
public int? Rate { get; set; }
public string Description { get; set; }
public string Image { get; set; }
[StringLength(50)]
public string Kind { get; set; }
public double? Height { get; set; }
public double? Weight { get; set; }
[InverseProperty("Pokemon")]
public virtual ICollection<PokemonsPokemonTypes> PokemonsPokemonTypes { get; set; }
}
}
using System.ComponentModel.DataAnnotations.Schema;
namespace DataModels.Models
{
public partial class PokemonsPokemonTypes
{
public int PokemonId { get; set; }
public int TypeId { get; set; }
[ForeignKey("PokemonId")]
[InverseProperty("PokemonsPokemonTypes")]
public virtual Pokemons Pokemon { get; set; }
[ForeignKey("TypeId")]
[InverseProperty("PokemonsPokemonTypes")]
public virtual PokemonTypes Type { get; set; }
}
}
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace DataModels.Models
{
public partial class PokemonTypes
{
public PokemonTypes()
{
PokemonsPokemonTypes = new HashSet<PokemonsPokemonTypes>();
}
public int Id { get; set; }
[StringLength(8)]
public string Type { get; set; }
[InverseProperty("Type")]
public virtual ICollection<PokemonsPokemonTypes> PokemonsPokemonTypes { get; set; }
}
}
This works pretty well!
One Product (Pokemon) can have Multipke Categories (Type).

There is one bug in your code listing, The [ForeignKey] attribute can be put on the foreign key property or the navigation property, but if on the Navigation property it needs to be set to point to the FK field name. (PokemonTypeId)
Two options to support more than one pokemon type:
If a Pokemon can have 1 or 2, but at max 2 types, then you can add two PokemonType references to the Pokemon. For example:
public int PrimaryPokemonTypeId { get; set; }
[ForeignKey("PrimaryPokemonTypeId")]
public virtual PokemonType PrimaryPokemonType { get; set; }
public int? SecondaryPokemonTypeId { get; set; }
[ForeignKey("SecondaryPokemonTypeId")]
public virtual PokemonType SecondaryPokemonType { get; set; }
If you can possibly refer to more than 2 types then you can adopt a many-to-many relationship rather than a 1 to many relationship. You can restrict the # of related types in code to two if you wish, but the data schema will support any number of types on a Pokemon.
A Pokemon would hold a collection of types. This means introducing a linking table. I.e. A PokemonTypePokemon.
If this is EF Core then you need to define the linking table:
public class Pokemon
{
// ... Pokemon fields...
public virtual ICollection<PokemonTypePokemon> PokemonTypes { get; set; } = new List<PokemonTypePokemon>();
}
public class PokemonType
{
// Classifications...
public virtual ICollection<PokemonTypePokemon> Pokemon { get; set; } = new List<PokemonTypePokemon>();
}
public class PokemonTypePokemon
{
public virtual Pokemon { get; set; }
public virtual PokemonType { get; set; }
}
This will require a little wiring up in the DbContext to associate the linking table. In the DbContext's OnModelCreating handler...
// EF Core
modelBuilder.Entity<Pokemon>()
.HasMany(x => x.PokemonTypes)
.WithOne(x => x.Pokemon)
.HasForeignKey("PokemonId");
modelBuilder.Entity<PokemonType>()
.HasMany(x => x.Pokemon)
.WithOne(x => x.PokemonType)
.HasForeignKey("PokemonTypeId");
You will likely need to configure the PK for the PokemonTypePokemon table as well to use a composite key on PokemonId & PokemonTypeId.
With EF6 you can map a HasMany().WithMany(), without needing the map the joining table in many cases. This should give you some idea where to start with the mapping change and joining table. Do a bit of Google-fu on EF Many-to-Many to refine.

Related

AutoMapper with Array and JsonApiSerializer.JsonApi.Relationship

I have an AppService solution with the following Classes and i want to map from the SourceObject to the DestinationObject
Source Classes
public class SourceObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<SourceChildObject[]> childObjects { get; set; }
}
public class SourceChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Destination Classes
public class DestinationObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<DestinationChildObject[]> childObjects { get; set; }
}
public class DestinationChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Auto mapper is setup in the sartup class
services.AddAutoMapper(typeof(EntityMappingProfile));
And my mapping class loos like this
public class EntityMappingProfile : Profile
{
public EntityMappingProfile()
{
CreateMap<SourceObject, DestinationObject>();
CreateMap<Relationship<SourceChildObject[]>, Relationship<DestinationChildObject[]>>();
}
}
When i execute the solution all fields are mapped apart form the array field of type JsonApiSerializer.JsonApi.Relationship. The destination field is null. What am i doing wrong?
You forgot about creating a map between SourceChildObject and DestinationChildObject. Add this line to your EntityMappingProfile.
CreateMap<SourceChildObject, DestinationChildObject>();
And one more thing, when you are mapping generic types, you can enable mapping for all types with:
CreateMap(typeof(Relationship<>), typeof(Relationship<>));
instead of creating a map with concrete use case of a generic type.

Entity Framework Core - How to include/populate a navigation property with custom(1-to-1) query in EF?

How to include/populate a navigation property with custom(1-to-1) query in EF?
e.g.
public class Item {
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Id")]
public ItemCost LatestCost {get; set; }
}
public class ItemCost {
public int Id { get; set; }
public DateTime From { get; set; }
public DateTime? To { get; set; }
public decimal Cost { get; set; }
}
Goal is to populate the LatestCost property of the Item with it's latest cost from ItemCosts. How is this being accomplished with EF or what's your take on this?
Is it possible to do a custom query within .Include/.ThenInclude methods?
e.g.
.ThenInclude(a => { a.LatestCost = (from a _db.ItemCosts
where... select a).SingleOrDefault() })...
You could use a virtual get-only property. Your nav property should really be an ICollection<ItemCost>. In this example I'm assuming the Id property in the ItemCost class is the id of the related Item, but it's not clear. Tip: using nameof(property) instead of hard-coding the property name will allow the compiler to catch errors with the name if you were to change it for some reason. The [NotMapped] attribute tells Entity Framework to not try and map the property to a database field.
public class Item {
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ItemCost> ItemCosts {get; set; }
[NotMapped]
public virtual ItemCost LatestCost
{
get
{
return ItemCosts.OrderByDescending(x => x.From).FirstOrDefault();
}
}
}
public class ItemCost {
public int Id { get; set; }
public DateTime From { get; set; }
public DateTime? To { get; set; }
public decimal Cost { get; set; }
[ForeignKey(nameof(Id))]
public virtual Item Item { get; set; }
}

Update database schema to allow multiple users

I'm working on an ASP.net Web API application and would like to allow multiple users to have access to their own data without changing the database schema too much.
My tables look a little like this:
public class Asset
{
public string Name { get; set; }
[Required]
public int Id { get; set; }
public string AssetTag { get; set; }
public string Serial { get; set; }
public int Model { get; set; }
}
public class Organisation
{
[Required]
public int Id { get; set; }
[Required]
public int DefaultLocation { get; set; }
public location Location { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string Contact { get; set; }
}
public class AssetModel
{
public string Name { get; set; }
[Required]
public int Id { get; set; }
public int CategoryId { get; set; }
public int ManufacturerId { get; set; }
public string ModelNumber { get; set; }
}
*fields omitted for brevity
Each user should be able to create their own assets / organisations / etc, but should not have access to any other users fields.
I'm yet to add authorization / authentication however I'm probably going to use token based auth as outlined here:
http://bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net-identity/
Should this be as easy as tacking each users GUID onto each column and applying some logic? Or will I need to completely re-design the database?

I'm using EF in my application. I try to save\insert a new record to a Patient View

I made a view in SQL server and then added to to my edmx file in visual studio 2012 I then went to POST it on Postman and got this runtime error.
Unable to update the EntitySet 'ViewPatient' because it has a DefiningQuery and no <InsertFunction> element exists in the <ModificationFunctionMapping> element to support the current operation.
//Controller action code namespace MvcWebAPI.Models
{
using System;
using System.Collections.Generic;
public partial class ViewPatient
{
public int PatientID { get; set; }
public int MedicationID { get; set; }
public int GPID { get; set; }
public string Firstname { get; set; }
public string Surname { get; set; }
public System.DateTime DOB { get; set; }
public string Medication { get; set; }
public string Alergies { get; set; }
public string MedicationHistory { get; set; }
}
}
You need a primary key on the view. http://blogs.msdn.com/b/alexj/archive/2009/09/01/tip-34-how-to-work-with-updatable-views.aspx

Better way to create database for a pricing system

I need to create a price table system so I am going to create these three tables in my database.
PricingTable (ID, Name, ServiceID, Style)
PricingTablePackages (ID, PricingTable_ID, Title, Price, PricePerTime, Info, Flag, Link)
PricingTablePackagesFeatures (ID, PricingTablePackages_ID, Feature, Value, MoreInfo)
Here one PriceTable can hold more then one PricingTablePackages and one PricingTablePackage can hold more then one PricingTablePackagesFeature.
Is any way to design a better model? In a single database Table ?
I am going to create a MVC3 Model for those table so what is the best way to do this kind of DB Table in a MVC3 Model?
I would use public virtual variables for 'lazy-loading' values when you need them using Entity Framework:
(variable types may be off depending on exactly what you want for each variable)
public class PricingTablePackages
{
public int ID { get; set; }
public int PricingTableID { get; set; }
public virtual PricingTable PricingTable { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public decimal PricePerTime { get; set; }
public string Info { get; set; }
public bool Flag { get; set; }
public string Link { get; set; }
}
public class PricingTablePackagesFeatures
{
public int ID { get; set; }
public int PricingTableID { get; set; }
public virtual PricingTable PricingTable { get; set; }
public string Feature { get; set; }
public string Value { get; set; }
public string MoreInfo { get; set; }
}
public class PricingTable
{
public int ID { get; set; }
public string Name { get; set; }
public int ServiceID { get; set; }
public virtual Service Service { get; set; } // if there is a Service class
public string Style { get; set; }
}

Resources