Unable to establish One to Many Relations in MVC 6 Views - asp.net

As a learning exercise, I was trying to form a simple One to many Relation between Vendors and Shops where each Vendor has multiple shops.
Using two model classes I achieved the following:
This is what scaffolding gives me for Shops
Why am I not getting a drop down here?
Not sharing any code as of now. As most of it is auto generated. Let me know if someone would like me to paste the code for my models.
Another doubt why are my table Columns alphabetically Ordered? If I am not mistaking entity framework 6 used to order it as per the class definition. Is there a way to override it? Cause the view scaffold seems to mirror the DB in terms of ordering objects.
Thanks.
Update:
I added a property Vendorid in the Shops Class. Now I see the Dropdown but no values. Do I need to get down to Fluent API for achieving this?
public class Shops
{
public int Id { get; set; }
public String Name { get; set; }
public int Rank { get; set; }
public String Address { get; set; }
public Boolean Active { get; set; }
public int VendorId { get; set; }
public Vendors Vendor { get; set; }
}
Vendors
public class Vendors
{
public int Id { get; set; }
public String Name { get; set; }
public int Rank { get; set; }
public Boolean Active { get; set; }
public ICollection<Shops> Shops { get; set; }
}
Env: Visual Studio 2015 (Latest ASP.net Patch Applied).
Project Template: Web Application

This depends on what approach on EF you are using. Are you sure they have relationship in their classes? If your using code first, you have to map it manually using fluent API. on OnModelCreating method on DbContext class, use something like this
modelBuilder.Entity().HasMany(v => v.Shop).WithOptional(s => s.Vendor).
If your using Database First, just create relationship on tables diagram(or script) and update the model on your project and EF will create it for you.

Related

EF Core with cosmos issue

I have a SQL database that I'm using currently with EF Core. I have 2 objects:
public class Contact
{
public Guid ContactGUID { get; set; }
public string Name { get; set; }
[ForeignKey("CreatedBy")]
[InverseProperty(nameof(User.ContactCreatedBy))]
public virtual User CreatedByUser { get; set; }
...
}
public class User
{
public User
{
User = new HashSet<Contact>();
}
public Guid UserGUID { get; set; }
[InverseProperty(nameof(Contact.CreatedByUser))]
public virtual ICollection<Contact> ContactCreatedBy { get; set; }
...
}
This all works fine with EF Core connected to SQL. But something I would like to do is take this object that I've grabbed and save it to a separate CosmosDB database with EF Core.
When I try to do that however, I get the following error:
Microsoft.EntityFrameworkCore: When creating the relationship between
'User.ContactCreatedBy' and 'Contact.CreatedByUser' the entity type
'Contact' cannot be set as principal.
What is the best way to get past this error? I'd rather not create a whole separate object for my cosmos database that basically looks the same but w/out all the inverseproperties/etc. Is there a way to do that, or do I have to go about the long way?

Circular Reference with Include in .NET Core

I am using code like below in .NET core
.Include(p => p.Company).ThenInclude(p => p.Country).ToList();
My classes look like below,
public partial class Company
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual Country Country { get; set; }
}
public partial class Country
{
public Country()
{
Companies = new HashSet<Company>();
}
public Guid Id { get; set; }
public string Name { get; set; }
public string ShortCode { get; set; }
public virtual ICollection<Company> Companies { get; set; }
}
And I want only Company and then Country in side the company to be populated. But I am getting the Company inside the Country and then Country in those Companies and so on populated which is causing the response delayed.
I have already tried difference examples of Include on Google/StackOverFlow.
This isn't actually a problem. EF has what's called "object fix-up". Internally, it uses an object cache. When it builds entity instances for database query results, it adds those to the object cache, allowing it to then pull out those objects later, rather than issuing the same queries again.
Because of this object cache, if it already existing entity instances corresponding to a relationship, it will auto-fill that relationship from the object cache. It's not issuing a series of circular queries forever.

Implement one-to-many relationship in ASP.NET MVC 5

This is my project model :
public class Project
{
public int ProjectID { get; set; }
public string ProjectTitle { get; set; }
public string ProjectDetails { get; set; }
public virtual ICollection<Proposal> Proposals{ get; set; }
}
This is my Proposal model :
public class Proposal
{
public int ProposalID { get; set; }
public string BidTitle { get; set; }
public string BidDetails { get; set; }
public virtual Project Project { get; set; }
}
As you can see, there is one-to-many relationship between Project and Proposal. In
mydomain/Project/Details/ProjectID
view, I want to put a button, when this button is clicked, user can create a new Proposal for that project. My question is how I can pass that project's information to bid? If you can give me some tips about it, I'd be really glad. Thanks.
Create a model known as a viewmodel, which includes both the models you want to use under the same view. Your would look something like this:
public class ProposalAndProjectModel
{
public Proposal Proposal { get; set; }
public Project Project{ get; set; }
}
Save it as something like ProposalAndProjectModel.cs and then in your view, reference this model.
Now in your view you will be able to do the following:
Model.Proposal.propertyName
or
Model.Project.propertyName
This should help you as for getting the correct parameters for creating new objects.
You say when user click button user goto another page. You can sen projectID as get to that page. Thats how you can get that projectID.

Dataannotation Foreignkey property name vs column name?

I am using System.ComponentModel.DataAnnotations in my domain classes with EF5 and framework 4.5
public class SalesOrderLine : LoggedEntity
{
[ForeignKey("SalesLine")]
[Required]
public int SalesLine_Id { get; set; }
public SalesLine SalesLine { get; set; }
}
However the example here uses the column name as the foreign key, not the navigation property name.
Is there any difference between the two ways of doing it?
[
There is no difference. Both usages do the same.
Which is clear or not clear depending on if you are using EF 5 with .NET 4.0 or with .NET 4.5.
In .NET 4.0 (where the ForeignKeyAttribute class is part of the EntityFramework.dll assembly) the description you'll see in Intellisense (when hovering over the attribute for example) says (emphasis by me):
Denotes a property used as a foreign key in a relationship. The
annotation may be placed on the foreign key property and specify the
associated navigation property name, or placed on a navigation
property and specify the associated foreign key name.
In .NET 4.5 (where the ForeignKeyAttribute class has been moved into the framework's System.ComponentModel.DataAnnotations.dll assembly) the description has become as informative as a tautology:
Denotes a property used as a foreign key in a relationship.
The example you posted shows how to use EF Code-first to create the navigation property of Manager and map it to type Person -
public class Project
{
public int ProjectId { get; set; }
public string Name { get; set; }
public int ManagerId { get; set; }
// The following will use ManagerId as the foreign key and map it to PersonId, or w/e the key field is for person
[ForeignKey("ManagerId")]
public Person Manager { get; set; }
}
Your code uses SalesLine_Id to establish the foreign key relationship to the SalesLine, which is of type SalesLine.
public class SalesOrderLine : LoggedEntity {
[ForeignKey("SalesLine")]
[Column("SalesLine_Id")]
[Required]
public int SalesLine_Id { get; set; }
public SalesLine SalesLine { get; set; }
}
What's important to understand is that you probably don't have to decorate your class with all of the annotations that you are, unless you are using an odd naming convention, because EF will automatically map everything the way you want it to provided the names are fairly consistent -
public class SalesOrderLine {
public int SalesOrderLineId { get; set; }
public string Description { get; set; }
public int SalesLineId { get; set; }
public virtual SalesLine SalesLine { get; set; }
}
public class SalesLine {
public int SalesLineId { get; set; }
public string Description { get; set; }
public ICollection<SalesOrderLine> SalesOrderLines { get; set; }
}
Would work just fine, as an example. If you need to make the relationship any more complicated you will probably need to start looking at using the Fluent API for configurations, but as is that code would work fine without dataannotations. Since SalesLineId is not nullable it is required, EF understands it is a foreign key, and everything is happy.

How to Handle caching with 3-tier design pattern in a website

Im developing a asp.net small website and thought about using 3-tier design pattern (Gui, BLL, DAL). My main problem is that i feel bit lost with how should i handle the caching right.
1.First, where should the caching be done? Is it in the GUI website or in the BLL?
2.Second, it feels too messy to me, any chance anyone could provide me a simple example of how caching is done in a good way with all 3 parts of the 3tier?
3.Last, do u find okay to use 3tier for my need?
Personally I really like 3-tier structure and I can only recommend it. Let's see a simple example with some minor caching. We focus on the structure now.
Let's suppose we have the following code-first structure.
public class BlogEntry
{
public int Id { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Blog> Blogs { get; set; }
}
public BlogContext : DbContext
{
public DbSet<Category> Category { get; set; }
public DbSet<BlogEntry> Entry { get; set; }
}
Mind that EF will create the primary and foreign keys in the DB by naming conventions (like "Id"). You can use Db-first model as well, not a problem.
Let's have some DTO objects (see MSDN or wiki) like:
public class CategoryDto
{
// To use in LINQ .Selector()
public Expression<Func<Category, CategoryDto>> Selector = efCategory => new CategoryDto
{
Id = efCategory.Id,
Name = efCategory.Name,
}
public int Id { get; set; }
public int Name { get; set; }
}
Of course categories are not changing often, so we may create some sort of cache for them. The caching in this case is clearly in BLL-level, using Dto objects. Update: This is good only if you have some data that is very unlikely to change but accessed very frequently. Otherwise don't bother with it.
public class MainCache
{
// Make it singleton
// Create some init and a refresh method, watch for thread-safety
public List<CategoryDto> Categories { get; set; }
}
So the controller level can access the cache like this: Update: Now the result of the action itself is cached, see details here. This is a safe solution, the framework does everything.
[HttpGet]
[OutputCache(Duration=10, VaryByParam="none")]
public ActionResult DisplayCategories()
{
// Calling BLL, receiving Dto objects
var model = MainCache.Instance.Categories;
return View(model);
}
Hope, you get it. I think this is a general structure that can be used in various situations. If something is not clear just ask.
Update: Minor code fix, and about caching

Resources