MVC code first approach not fetching data from table using DbContext - c#

I am using the code-First approach of MVC facing the below issue.
I have 1 The Admin model which has 2 properties that represent a separate class as shown below respectively.
public class Admin
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public List<IdProof> IdProofDocs { get; set; }
public Subscription subscription { get; set; }
}
public class IdProof
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string File { get; set; }
}
public class Subscription
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public double TotalAmount { get; set; }
public double PaidAmount { get; set; }
}
When I try to save it, it successfully saves values in 3 tables including the last 2 (i.e. IdProof, Subscription) of the Admin Model. see below code
[HttpPost]
public ActionResult AddHotel(Admin admin)//saving correctly in 3 table i.e. admin, subscription,IdProof
{
dbContext.Admins.Add(admin);
dbContext.SaveChanges();
return RedirectToAction("someActionMethod");
}
till now it's good, but from here
when I try to get records by using the below code
public ActionResult AllAdmins()
{
List<Admin> ListAdmin= dbContext.Admins.ToList();//here its fetching records from admin table only ;(
return View(ListAdmin);
}
It gives me only Admin table data, not the other 2 tables*** i.e IdProof & Subscription. I was wondering that EF automatically saves data in the other 2 tables by its model, so at the time of fetching why it's not giving me data from the other 2 tables.
I am using the Code-First approach in mvc5, what is needed to change in my code. I am new in mvc.
Thanks in advance

You need to include other tables if you want EF to load it for you.
List<Admin> ListAdmin= dbContext.Admins
.Include(x => x.IdProofDocs).Include(x => x.Subscription).ToList()

EF is having concept of Lazy Loading and Eager Loading.
Lazy Loading
In Lazy loading EF not load the related entities until ask for it.
Link: https://www.entityframeworktutorial.net/lazyloading-in-entity-framework.aspx
Eager Loading
In Eager Loading, Related Entity mentioned at the Query time using Include method.
Link : https://www.entityframeworktutorial.net/eager-loading-in-entity-framework.aspx
Depend on requirement, you can choose option.

Related

Entity Framework ignore not included foreign keys

In my .net 6.0 project I use the Entity Framework 6 to get data from my database.
My model contains a foreign key, which is used to resolve the data of the id.
I use the following call to resolve the foreign key:
// ...
_context.Tools.Include(t => t.User).ToListAsync();
// ...
My Tool Model looks like this:
[Table("MY_TOOLS")]
public class Tool
{
[Key]
[Column("ID")]
public int Id { get; set; }
[Column("UPDATED_BY")]
public int? UpdatedBy { get; set; }
[ForeignKey("UpdatedBy")]
public User? User { get; set; }
}
My User class looks like this:
[Table("MY_USERS")]
public class User
{
[Key]
[Column("ID")]
public int Id { get; set; }
[Column("EMAIL")]
public string? Email { get; set; }
}
When I leave the include like described above, the user is resolved correctly.
Is there a way to remove the user property from the loaded data, when I don't explicitly tell the Model to resolve the foreign key?
It shouldnt resolve it by default as it uses lazy loading. You would have to query it specifically for the user object to get it e.g. _context.My_Tools.include(uvar = uvar.User).FirstOrDefault();
So you just make a method called getToolEager() and one called getTool()
it would be a "waste" of a call to query for the user object only to throw it away in case you might not need it.
You have 2 options:
Lazy Loading Proxy
Use Lazy Loading as described here:
https://learn.microsoft.com/en-us/ef/core/querying/related-data/lazy
After just load data as _context.Tools.ToListAsync(); and users will load when you try access them.
Manually load related data
Modify Tool to explicitly store User FK:
[Table("MY_TOOLS")]
public class Tool
{
[Key]
[Column("ID")]
public int Id { get; set; }
[Column("UPDATED_BY")]
public int? UpdatedBy { get; set; }
[ForeignKey("UpdatedBy")]
public User? User { get; set; }
public int? UpdatedBy{ get; set; }
}
So when you load data as _context.Tools.ToListAsync(); fieldUser will be null but UpdatedBy will have User Id(if FK is not null in DB), so you can manually load them manually like tool.User = await _context.Users.FirstOrDefaultAsync(t => t.Id == tool.UpdatedBy);

Model is not fully loaded out of DB after save from EF-Core

I have a EF-Core Code-First apporach. Im Saving a HolderModel into a Database which contains a ID and a List of Models.
On Saving everything works fine. The Struktur is correct and all data is in the Database. But if i load the data back into my code, the List of Models is gone.
Im a bit confused as usally EF did everything by him self.
Am i missing something for EF-Core ?
Here is the codesnippet:
DB-Context:
public DbSet<FinancialStateHolderModel> States { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseSqlServer(
#"Server=.\;Database=Stock;User Id=dbuser;Password=dbuser");
builder.EnableSensitiveDataLogging(true);
}
HolderModel:
public class FinancialStateHolderModel
{
[Key]
public String Symbol { get; set; }
public List<FinancialStatementModel> Financials { get; set; }
}
Models:
public class FinancialStatementModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime Date { get; set; }
}
Please check Loading Related Data in Entity Framework.
You're looking for
Eager loading - the related data is loaded from the database as part
of the initial query
In your case(example not exact syntax because I don't know what your call looks like)
should be context.FinancialStateHolders.Include(x=> x.FinancialStatements)

Entity Framework : Eager loading not working with string foreign key

I am having trouble loading a child entity using eager loading, the eager loading works fine everywhere else in the project but its not working with any of the string foreign keys. My model is :
public class Listing : BaseAudit<int>
{
public int? CommunityId { get; set; }
public string LotId { get; set; }
public Lot Lot { get; set; }
}
public class Lot : BaseAudit<string>
{
public ICollection<Listing> Listings { get; set; }
}
public class BaseAudit<T> : BaseId<T>
{
public BaseAudit()
{
CreatedDate = DateTime.Now;
}
public DateTime? CreatedDate { get; set; }
public string CreatedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public string UpdatedBy { get; set; }
}
public class BaseModel
{
public BaseModel()
{
Active = true;
}
public bool Active { get; set; }
}
public class BaseId<T> : BaseModel
{
public T Id { get; set; }
}
I am trying to load Lot property of Listing I have tried:
_db.Listings.Where(m => m.CommunityId == communityId && m.LotId != null).Include(a => a.Lot).ToList();
I have checked that it is generating correct SQL by using a break point but It is always returning with all Lot properties null. I can not figure out what am I doing wrong here.
Short answer: Listings should be a virtual collection; LotId is never null, and Include should be immediately after your DbSet. And you should probably model your inheritance strategy
Long answer
It seems you tried to configure a one-to-many relationship between Lots and Listings: Every Lot has zero or more Listings and every Listing belongs to exactly one Lot.
For a proper one-to-many you should declare your collection of Listings virtual
public virtual ICollection<Listing> Listings { get; set; }
Because of the one-to-many relation, there is no Listing without a Lot Therefore the foreign key to Lot's primary key LotId is never null.
So you have a nullable int communityId (is that true? or is communityId an int?), and you want all Listings that have the same value for Listing.CommunityId inclusive the one and onlyLotthisListing` has:
using System.Data.Entity;
List<Listing> result = dbContext.Listings
.Include(listing => listing.Lot)
.Where(listing => listing.communityId == communityId)
.ToList();
If this doesn't help, then your use of inheritance might cause the problems. Relational databases don't know the concept of inheritance. You should tell entity framework using fluent API (or attributes) which inheritance strategy to model into tables. See Inheritance Strategies
Finally I see that some primary keys are int, and some primary keys are strings. Is that really intended? Is it useful?
EF6 does not support Include with Where on related entities.
A possible workaround: Entity Framework: Filtering Related Entity Collections
As of Entity Framework 6, there isn’t a way to filter which related
entities are loaded when using .Include().

Invalid Column exception

Hi guys I am getting this exception when I try to run the vehicles page.
Invalid column name 'MakeID'.
I have two models:
public class Vehicle
{
public int VehicleID { get; set; }
public string Title { get; set; }
[ForeignKey("Make")]
public int MakeID { get; set; }
public virtual Make Make { get; set; }
}
public class Make
{
public int MakeID { get; set; }
public string Title { get; set; }
}
The error is being thrown in my vehicles controller here
public ActionResult Index()
{
var vehicles = db.Vehicles.Include(v => v.Make);
return View(vehicles.ToList());
}
Add/Enable Migrations. Update the Database. Most of the case improper update causes the issue. There is no problem with your above code.
Make sure: you have Updated the Database Tables after adding new columns.
Run the Update-Database command in Package Manager Console.
Make sure your column Foreign Key Relationship / Mappings are ok.
You have to check it out manually.
There are four ways to Drop and Create the Database. Based on several conditions. OR you can manually delete the Database from SQL Server.
Good Article and Source can be found here - Programatically.
Note: Recreating the Database will lose the entire existing data. There is one way to avoid this problem. It's providing Seed Data to the database / Tables on create.

Lazy loading not working when adding detached entity

I have an ASP.NET MVC 4 application using Entity Framework 5 under .NET 4.5. The problem I'm having is that when I insert a detached entity that was created on the front-end, the lazy loading is not working.
Here is my code to add (or update):
public static int PersistMergeEntity(EntityTwo entityTwo)
{
int entityId;
using (var _db = new EntityDb())
{
if (_db.EntityTwo.Any(e => e.EntityTwoId == entityTwo.EntityTwoId))
{
_db.Entry(entityTwo).State = EntityState.Modified;
}
else
{
_db.EntityTwo.Add(entityTwo);
}
_db.SaveChanges();
//_db.Entry(entityTwo).Reference(e => e.EntityOne).Load();
entityId = entityTwo.EntityOne.EntityId;
}
EntityBo.UpdateData(entityId);
return entityTwo.EntityTwoId;
}
Here are my entities:
public class EntityTwo
{
[Key]
[ForeignKey("EntityOne")]
public int EntityTwoId { get; set; }
public Decimal NbValue { get; set; }
public virtual EntityOne EntityOne { get; set; }
}
public class EntityOne
{
[Key]
[ForeignKey("EntityTwo")]
public int EntityOneId { get; set; }
[ForeignKey("Entity")]
public int EntityId { get; set; }
public CsMonthDomain CsMonth { get; set; }
public int NbYear { get; set; }
public Decimal NbValue { get; set; }
public virtual Entity Entity { get; set; }
public virtual EntityTwo EntityTwo { get; set; }
}
And Entity is another entity that I need to do calculation every time I update or add EntityTwo.
The code works when the commented line is uncommented. But if it is the way shown up there, lazy loading will not work and I'll get a null Exception.
Lazy loading is set to true and the entities are, supposedly, correct, since it works when I explicitly load the navigation property.
I'm sorry about the names, but unfortunately I cannot post the real code ;(
Lazy loading does not work because the entityTwo you pass into the method is (most likely) not a dynamic proxy which it has to be in order to make lazy loading work. The instance is probably created outside the method using entityTwo = new EntityTwo();. To create a proxy of an entity you would need a context instance available and then use
entityTwo = _db.EntityTwos.Create();
In my opinion using explicit loading (your commented line) is the best solution in this situation. It has the same costs of querying the database once per navigation property like lazy loading would have plus the additional benefit over lazy loading that you could project a selection of properties you only need from the related entity, for example:
entityId = _db.Entry(entityTwo).Reference(eTwo => eTwo.EntityOne).Query()
.Select(eOne => eOne.EntityId)
.Single();

Categories