How can I use EF Core to display data from 3 different tables in my application - sql-server

I have 3 different tables, Customer, Vehicle, Contact.
The customer and vehicle tables share the common key ReferenceID and the customer and contact table share the key ContactID.
I want to be able to use EF core to display data from all three tables and was wondering if there is a way to do it without using JOIN?
Below is my attempt but I get this error: SqlNullValueException: Data is Null. This method or property cannot be called on Null values.
public class Customer
{
public string Name { get; set; }
[ForeignKey("Vehicle")]
public string ReferenceID { get; set; }
[ForeignKey("Contact")]
public string ContactID { get; set;}
public ICollection<Contact> Contact { get; set; }
public ICollection<Vehicle> Vehicle { get; set; }
}
public class Vehicle
{
public string ReferenceID { get; set;}
public string Make {get; set;}
}
public class Contact
{
public string ContactID {get; set;}
public string Name {get; set;}
}

You don't need the JOINS here, You already have the access to the other tables as Navigation Property. If you are not using the Lazy loading the properties Vehicle and Contact will load their data.
If the values didn't get load, you can load them as below.
var customers = _context.Customers.Include("Contact").Include("Vehicle");

Related

Advanced NoSQL Query (RavenDB)

I'm trying to run a query that gets all of my references, but it isn't working.
What I have right now is
from UserGroups
where Id="ActionGroup"
select Accomplishments.ID, Accomplishments.Accomplish
But I need only the Accomplishments.Accomplish that belong in my other collection ActivityAccomplishments and these are nested in another object.
To be exact, I'm trying to figure out how to query the UserGroups collection and only look at the one with id="ActionGroup". After that I need all of the Accomplishments.Accomplish strings within the UserGroup list to be filtered out if they don't match a id in ActivityAccomplishment.
Basically, in the UserGroup I'm looking at it's List Accomplishments needs to filter out all strings within the Acc class that don't match an Id in ActivityAccomplishments. Can someone please help me.
Here are the classes I'm using.
public class UserGroups
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Acc> Accomplishments { get; set; }
}
public class Acc
{
public string Id { get; set; }
public List<string> Accomplish { get; set; }
}
public class ActivityAccomplishments
{
public string Id { get; set; }
}
try this:
from UserGroups
where Id = "ActionGroup" AND Accomplishments[].Accomplish != "theIdYouDontWant"
select Accomplishments[].Accomplish as AccomplishStringsList
(not necessary to add the 'as AccomplishStringsList' - it is just a name for the results)

Is it possible to have another object type as a property of SQL Server entity without using relation

I have smaller separate models I don't want to map to SQL Server database table. Is it possible to use them as properties of an object that's mapped to SQL Server table?
I know SQL Server is relational, but of a case where I don't to map these separate models to database table? I have done it several times with non relational databases like MongoDb.
Here is and example what I want to achieve
The DbContext class:
public class ApplicationDbContext: DbContext
{
....
public DbSet<User> Users {get; set;}
}
User class:
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public LoginProfile LoginProfile { get; set; }
}
LoginProfile class:
public class LoginProfile
{
public string Username { get; set; }
public string Password { get; set; }
}
In the above example User model class is the only one I want to have as table in my database. Is it possible to do that, and do things like
var password = user.LoginProfile.Password;
user.LoginProfile.username = "username";

EFCore: Query a related entity based on the maximum value in a field in the related entity

I need to query a related entity based on the maximum value in a field in the related entity, and then display results from that item.
For example, the models are defined:
public class Student
{
public int StudentID {get; set;}
public string Name {get; set;}
public ICollection<ReportCard> ReportCards {get; set;}
}
public class ReportCard
{
public int ReportCardID {get; set;}
public int ProjectID { get; set; }
public Project Project { get; set; }
public int Result {get; set;}
public int Comment {get; set;}
public DateTime PublishDate {get; set;}
}
In the razor controller:
public class LatestResultsModel : PageModel
{
...
public IList<Student> Students {get; set;}
public async Task<IActionResult> OnGetAsync()
{
Students = await _context.Student
.Include(student => student.ReportCard)
.ToListAsync();
}
}
In the razor view:
#foreach (Student student in Model.Students)
{
<p>#student.Name</p>
<p>#student.ReportCard.Max(i => i.PublishDate).Result.ToString()</p>
}
After the Max statement I cannot query the other fields.
I've tried a few things to achieve this outcome of filtering the related data.
Filtered Includes are not supported.
Is there some type of join that could achieve this outcome?
It also doesn't handle the situation when a Student has no ReportCard. InvalidOperationException: Nullable object must have a value.
After the Max statement I cannot query the other fields. I've tried a few things to achieve this outcome of filtering the related data.
Yes! You cannot! because Max statement select only the field that you mention in the Max.
It also doesn't handle the situation when a Student has no ReportCard. InvalidOperationException: Nullable object must have a value.
Do as follows to overcome both problems:
#foreach (Student student in Model.Students)
{
<p>#student.Name</p>
if(student.ReportCards.Count > 0)
{
<p>#student.ReportCards.OrderByDescending(rc => rc.PublishDate).FirstOrDefault().Result.ToString()</p>
<p>#student.ReportCards.OrderByDescending(rc => rc.PublishDate).FirstOrDefault().PublishDate.ToString()</p>
}
else
{
<p>Student has no report card!</p>
}
}

Entity Framework - adding to auto generated table

I am working on a code first .NET application that has an auto generated table. I created my Order class, with a link to Item. Instead of manually creating an OrderItem class, I simply used List<Item> and it auto generated the OrderItem table for me;
[Table("Orders")]
public class Order
{
[Key]
public int OrderId { get; set; }
public virtual List<Item> Items { get; set; }
public string OrderNumber { get; set; }
}
This, as expected has made a table in the database called OrderItems
Many years later, we now want to reference OrderItems from another table within entity framework. However, as it is not a class we can physically reference, we are not sure how to do it in code. Obviously changing the database is easy, but that won't help for code first.
I'd like to do something like the following
[Table("AnotherTable")]
public class AnotherTable
{
[Key]
public int AnotherTableId { get; set; }
public string SomethingHere { get; set; }
public virtual OrderItem OrderItem { get; set; }
}
Which I cannot do, as OrderItem isn't a class it understands.
Is my only alternative to try and recreate in code, what EF auto created for me? I.e
[Table("OrderItems")]
public class OrderItem
{
public virtual Order Order_OrderId { get; set; }
public virtual Item Item_ItemId { get; set; }
}

How to Increase the performance of Entityframework ExecuteSqlCommand() with different ObjectContexts?

We are Using Service fabric Actor application,in that we have multiple actors. if i want to Update 10 records each record acts as like different individual instance.so when we insert it will create new ObjectContext everytime. so we con't store cache data in context level. so my datamodel is like
public class StudentData {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public String StudentId { set; get; }
public string StudentName {get;set;}
public String StudentAge { set; get; }
public string StudentDob {get;set;}
public String StudentSTD { set; get; }
public string StudentEmail {get;set;}
public String StudentAddress { set; get; }
public string StudentReligion {get;set;}
}
And when we want to update 10 students 10 object instances will create. so for every instance it will call the below method. so below method will call 10 times as different instance id.
public async Update(){
using(var context = new DatabaseContext()){
context.InfoObjectDatas.Attach(studentObj);
context.Entry(studentObj).State = System.Data.Entity.EntityState.Modified;
await context.SaveChangesAsync();
} }
We are Using Service fabric Actor application,in that we have multiple actors. if i want to insert 10 records each record acts as like different individual instance.so when we insert it will create new ObjectContext everytime. so we con't store cache data in context level. so my datamodel is like
public class StudentData {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public String StudentId { set; get; }
public string StudentName {get;set;}
public String StudentAge { set; get; }
public string StudentDob {get;set;}
public String StudentSTD { set; get; }
public string StudentEmail {get;set;}
public String StudentAddress { set; get; }
public string StudentReligion {get;set;}
}
And when we want to insert 10 students 10 object instances will create. so for every instance it will call . so i am using like for loop for 10 objects.
public async insert(){
using(var context = new DatabaseContext()){
Student st=new Student();
context.StudentData.Add(st);
context.StudentData.SaveChanges();
} }

Resources