using EF Core IdentityContext and DbContext both for order management - asp.net-core

I am working on creating an ecommerce website on ASP MVC Core 2. I inherited my user from IdentityUser and inherited context from IdentityDbContext for working with user data and inherited a different context from DbContext for working with products and orders etc.
Now, I want to link an order or shopping cart to a particular user and can not wrap my head around how to refer to the user in order table as they are in different contexts. I am also using the default guid created by EF as primary key in both the tables.
Should I ditch DbContext and use IdentityDbContext only? Does doing this causes problems with async methods in identity and other usual non async methods.
Here are some code snippets from my classes
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace shophe1.Models
{
public enum Gender { Male, Female, Other}
public class User : IdentityUser
{
public string FullName { get; set; }
public Gender Gender { get; set; }
public string ReferralID { get; set; }
public DateTime RegistrationDateTime { get; set; }
public string ActivationDateTime { get; set; }
public string UserType { get; set; }
public Wallet Wallet {get;set;}
public virtual ICollection<UserBankDetail> BankDetails { get; set; }
public virtual ICollection<UserAddress> AddressDetails { get; set; }
//public ShoppingCart Cart { get; set; }
//public ICollection<Order> Orders { get; set; }
}
}
Order class
using System.Collections.Generic;
namespace shophe1.Models
{
public class Order
{
public string OrderId { get; set; }
public ICollection<product> CartProducts { get; set; }
//public User User { get; set; }
public decimal OrderTotal { get; set; }
public decimal ShippingCharges { get; set; }
}
}
The issue is if I add user in order model and a collection of orders in user class, both contexts get mixed up and when migrating, all user and product related models get clubbed in same migration whether I use DbContext or IdentityContext in migrations --context option. This is because both user and orders are now interrelated.
Please advice.

Inherit your context from IdentityDbContext. You should have one context per database, ideally - especially if you want to relate the entities to each other.
If you actually want separate databases, such that the Identity tables reside in one, while your application tables reside in another, then you won't be able to directly relate the entities with each other. However, you can still create a pseudo-foreign key, where you simply store the id of a particular user in a column on one of your entities. You'd then merely need to issue a separate query on the other context with this id to fetch the user manually. For example:
var order = await appContext.Orders.FindAsync(orderId);
var user = await identityContext.Users.FindAsync(order.UserId);

Related

OData EF Core multiple self referencing table

First up, this was working in EF6 however I can't seem to get it working in OData EF Core. In EF6 I was using VisualStudio's .edmx designer
I have a single Table called FacilityStructure which represents a hierarchy of
Facility
Building
Floor
Zone
Site
ie, a Facility can have 0 or more Buildings, a Building can have 0 or more Floors etc ..
The SQL Table is basically
Id PK INT NOT NULL
StructureType INT NOT NULL (0 = Facility, 1 = Building etc)
ParentId INT NULL
Name NVARCHAR(255) NOT NULL
The table is self referencing through ParentId and works fine - I also have a SQL View which basically self joins for each StructureType to give the Parent, Grand Parent, Great Grand Parent etc such that a bottom level Site record through this view shows its Zone, Floor, Building and Facility resulting in the following POCO
public partial class FacilityStructure
{
public int Id { get; set; }
public int StructureType { get; set; }
public Nullable<int> ParentId { get; set; }
public string Name { get; set; }
public Nullable<int> FSFacilityId { get; set; }
public Nullable<int> FSBuildingId { get; set; }
public Nullable<int> FSFloorId { get; set; }
public Nullable<int> FSZoneId { get; set; }
public Nullable<int> FSSiteId { get; set; }
[ForeignKey(nameof(FSFacilityId))]
public virtual FacilityStructure FSFacility { get; set; }
[ForeignKey(nameof(FSBuildingId))]
public virtual FacilityStructure FSBuilding { get; set; }
[ForeignKey(nameof(FSFloorId))]
public virtual FacilityStructure FSFloor { get; set; }
[ForeignKey(nameof(FSZoneId))]
public virtual FacilityStructure FSZone { get; set; }
[ForeignKey(nameof(FSSiteId))]
public virtual FacilityStructure FSSite { get; set; }
}
I have attributed the Navigation properties (FSFacility, FSBuilding etc) with their ForeignKey columns.
Since I am using OData EF Core and it has its own ODataModelBuilder which simply
builder.EntityType<FacilityStructure>().HasKey(e => e.Id);
and the ModelBuilder in OnModelCreating of the DbContext does similar with mapping to the correct View
builder.Entity<FacilityStructure>(entity =>
{
entity.HasKey(e => e.Id);
entity.ToTable("FacilityStructure", "odata");
});
but when I query the OData controller which simply
[EnableQuery]
public IQueryable<FacilityStructure> GetFacilityStructures()
{
return db.FacilityStructures;
}
I get the following runtime error ..
The query specified in the URI is not valid.
Unable to determine the relationship represented by navigation
property 'FacilityStructure.FSFacility' of type 'FacilityStructure'.
Either manually configure the relationship, or ignore this property
using the '[NotMapped]' attribute or by using
'EntityTypeBuilder.Ignore' in 'OnModelCreating'."
So its complaining about not being able to work out the relationship for FSFacility and I should manually configure it, which I think I am doing via the [ForeignKey()] attribute. The weird thing is if I comment out 3 of the relationships (FSFloor, FSZone, FSSite) then it works, I get data and I can $expand on FSFacility,FSBuilding which work. As soon as I add a 3rd relationship then the error returns.
This seems like a bug to me in EF Core since I am explicitly defining the 0:1 relationship and it works if 2 are defined but not for 3 or more.
I realise now that I should have perhaps split the single self referencing table into tables for each StructureType but this decision was actually made years ago and I am now porting the .NET Framework monolithic Webapp to .NET Core and Microservice architecture but require the monolithic Webapp to continue to work
Any help much appreciated

MVC editing model relationships from database first

Building web app with MVC5 using database first modeling approach. Unfortunately, the existing database that I'm building from has a table that's missing foreign key constraints, has extra primary keys and is not generally well formed. Because of this, when I build the MVC model, it can't automatically generate all of the necessary many to many relationships between the tables. I can't change the original table's definition.
I discovered the ability to create new associations through the MVC model diagram and the Model Browser, but it only seems to allow me to associate the tables and not specify the fields that join them. When I update the model, I get errors about the associations I created not mapping, without any details.
All the examples I can find for database first modeling start with well-formed and well-named tables, which is not always the case in real life.
Can someone explain or point me to a link about how to start with a database first model but then fix the problems or define the missing pieces so that the MVC model can build correctly?
Or maybe for this one table, I should just model the class directly? The only part of that I don't understand is where I define the details of the navigation properties so the model knows what tables and fields to join.
Directed by the comment above, I eventually determined a much better approach to creating an MVC app for an existing database that may not be designed the way you want to lay out your model.
I am using a CodeFirst approach of defining the Model classes directly instead of generating them from the existing database. Then, using Entity Framework mapping properties, I map each class and its individual properties to the existing table and fields. This lets me define the class however I wish, give it the property names I want and define the foreign keys that may not be defined in the database.
Here's some examples of classes that I created that map to existing database tables.
[Table("uofs00137_contacts")]
public partial class Contact
{
[Key]
[Column("id")]
public int ID { get; set; }
[Column("first_name")]
[StringLength(30)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Column("last_name")]
[StringLength(30)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Column("organisation")]
[StringLength(30)]
[Display(Name = "Organization")]
public string Organization { get; set; }
[Column("title")]
[StringLength(30)]
[Display(Name = "Job Title")]
public string JobTitle { get; set; }
[Column("email")]
[StringLength(40)]
[Display(Name = "Email")]
public string Email { get; set; }
[Column("status_code")]
[StringLength(1)]
[Required]
[Display(Name = "Contact Status Code")]
public string StatusCode { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
public virtual ICollection<DepartmentContact> DepartmentContacts { get; set; }
}
[Table("uofs00137_dept_contacts")]
public partial class DepartmentContact
{
[Key]
[Column("id")]
public int ID { get; set; }
[Column("department_code")]
[StringLength(7)]
[ForeignKey("VirtualDepartment")]
[Display(Name = "Department Code")]
public string DepartmentCode { get; set; }
[Column("contact_id")]
[ForeignKey("Contact")]
[Display(Name = "Contact ID")]
public int ContactID { get; set; }
[Column("status_code")]
[StringLength(1)]
[Required]
[Display(Name = "Department Contact Status Code")]
public string StatusCode { get; set; }
[Display(Name = "Department Contact Status")]
public string StatusDesc
{
get
{
if (StatusCode == "I")
return "Inactive";
else if (StatusCode == "A")
return "Active";
else
return "Unknown Status";
}
}
public virtual VirtualDepartment VirtualDepartment { get; set; }
public virtual Contact Contact { get; set; }
}
The connection to the database is made via a DbContext class:
public partial class AccountingAdminEntities : DbContext
{
public AccountingAdminEntities() : base("name=AccountingAdminEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// This is necessary so that as you add new items to the context
// you don't get the following exception:
// The model backing the AccountingAdminEntities context has
// changed since the database was created. Consider using Code
// First Migrations to update the database.
Database.SetInitializer<AccountingAdminEntities>(null);
base.OnModelCreating(modelBuilder);
}
public virtual DbSet<Contact> Contacts { get; set; }
public virtual DbSet<DepartmentContact> DepartmentContacts { get; set; }
}
Entity Framework follows some conventions to "assume" certain properties, such as a field named id will be a key, but I chose to explicitly define all the mapping properties for clarity.
This approach allowed me to accomplish my goal of generating an MVC app for an existing database and follow our naming conventions without needing to change the database or add foreign key constraints to it.
Other reference links here:
https://blogs.msdn.microsoft.com/efdesign/2010/06/01/conventions-for-code-first/
and here:
https://msdn.microsoft.com/en-us/data/jj591617.aspx#1.1

How to cast Entity framework Objects in Web API?

I'm using entity framework and I figured out that it ain't able to serialize the output of
EDM Objects. For now I'm using Northwind Products-table. SO thereforth I'm forced to cast the Object to another and are using the .Cast but it doesn't work.
The only solution I have is to property by property do it manually in my code, but I'm thinking - there must be a better way!
For god's sake - it is 2013! And this Entity seems like a good idea in the beginning but it has so many gotchas and constraints that it actually hinders more than it helps, but anyway the EDMX diagrams are nice!
Anybody who has a better solution to casting the objects?
POCO
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
//public Nullable<int> SupplierID { get; set; }
//public Nullable<int> CategoryID { get; set; }
public string QuantityPerUnit { get; set; }
public Nullable<decimal> UnitPrice { get; set; }
public Nullable<short> UnitsInStock { get; set; }
public Nullable<short> UnitsOnOrder { get; set; }
public Nullable<short> ReorderLevel { get; set; }
//public bool Discontinued { get; set; }
public Category Category { get; set; }
//public ICollection<Order_Detail> Order_Details { get; set; }
//public Supplier Supplier { get; set; }
}
View Model
public class ProductsViewModel
{
public List<POCO.Product> Products { get; set; }
public ProductsViewModel()
{
using (NorthwindEntities dNorthwindEntities = new NorthwindEntities())
{
this.Products = dNorthwindEntities.Products.Cast<POCO.Product>().ToList();
Web api controller:
public class ProductsController : ApiController
{
public List<Product> GetAllProducts()
{
var viewmodel = new ProductsViewModel();
return viewmodel.Products;
}
1.
You can use frameworks like AutoMapper to handle Entities to ViewModel / DTO mapping automatically.
2.
Using Entities in the View (even in their POCO form) is not recommended for couple of reasons:
Security: Sending entities back to the client/view may expose more data than you intended.
Serialization: Since your entities usually contain reference to another entities and those entities may contain a reference back to the (parent) entity, you have to configure your serializer to handle this situation otherwise you'll get Circular Dependency Exception.
Incompatibility: The structure of your entity may not be compatible with what your view/client needs to render itself. Sometimes your view just needs a simple string while the entity holds this data in a much complex way hence the view needs to 'extract' it and you end up with a view full of unnecessary entity-drill-down code.

ASP.NET MVC 4 database scaffolding self referential model

I have a constructed a model using code first in C#. The model literally represents a container element for a website building application, in other words, the model defines a Div tag or some such HTML element. Like a Div tag which can contain multiple child elements, I have tried to represent this in my model, but the scaffolding to the DB, does not give me what I'd expect.
I should get a new many to many joins table, but instead I only get a single column in the DB which expects a single int data type.
Here is the model:
public class ElementContainer
{
public int ElementContainerID { get; set; }
public int PageId { get; set; }
public int? ParentElementContainerID { get; set; }
public string ElementContainerName { get; set; }
public ElementType ElementType { get; set; }
public string ElementClass { get; set; }
public PageAsset PageAsset { get; set; } // content of container
public List<ElementContainer> NestedContainers { get; set; }
}
The last line is the self-referential attribute which just appears as a column called ElementContainer_ElementContainerID
Thanks in advance!
I agree with Bahman, DB first is easier.
While I haven't tried to do what you are trying, your code looks like a self-Join that would do exactly what you describe.
This is a One-to-Many relationship. EF Navigation will pull a List of all nested children containers.
If you want to create a many-to-many relationship with EF Code-First, you should create another Entity
public class ContainerChildren
{
public int ElementContainerID { get; set; }
public List<ElementContainer> NestedContainers { get; set; }
}
this reference should help you to get the exact idea http://blogs.msdn.com/b/wriju/archive/2011/05/14/code-first-ef-4-1-building-many-to-many-relationship.aspx

How to map and reference entities from other data sources with NHibernate

I'm currently working on and ASP.NET MVC application in which I have a User entity like follows:
public class User
{
public virtual int Id { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string Role { get; protected set; }
public virtual Location Location { get; protected set; }
}
Where location is just as straightforward:
public class Location
{
public virtual string Id { get; protected set; }
public virtual string Building { get; protected set; }
public virtual string City { get; protected set; }
public virtual string Region { get; protected set; }
}
My complication arises because I want to populate the User from Active Directory and not the database. Additionally, several classes persisted to the database reference a user as a property. I've got an ADUserRepository for retrieval, but I don't know how to integrate these Users into my object graph when the rest is managed by NHibernate.
Is there a way for NHibernate to persist just an id for a User without it being a foreign key to a Users table? Can I map it as a component to accomplish this? I've also looked at implementing IUserType to make the translation. That way it would map to a simple field and ADUserRepository could be put in the chain to resolve the stored Id. Or am I trying to hack something that's not really feasible? This is my first time around with NHibernate so I appreciate any insight or solutions you can give. Thanks.
Update
It appears my best solution on this will be to map the User with an IUserType and inject (preferably with StructureMap) a service for populating the object before its returned. Framed in that light there are a couple of questions here that deal with the topic mostly suggesting the need for a custom ByteCodeProvider. Will I still need to do this in order for IUserType to take a parameterized constructor or do the comments here: NHibernate.ByteCode.LinFu.dll For NHibernate 3.2 make a difference?
using a Usertype to convert user to id and back
public class SomeClass
{
public virtual string Id { get; protected set; }
public virtual User User { get; protected set; }
}
// in FluentMapping (you have to translate if you want to use mapping by code)
public SomeClassMap()
{
Map(x => x.User).Column("user_id").CustomType<UserType>();
}
public class UserType : IUserType
{
void NullSafeSet(...)
{
NHibernateUtil.Int32.NullSafeSet(cmd, ((User)value).Id, index);
}
void NullSafeGet(...)
{
int id = (int)NHibernateUtil.Int32.NullSafeGet(cmd, ((User)value).Id, index);
var userrepository = GetItFromSomeWhere();
return userrepository.FindById(id);
}
}