Including related data using Entity Framework - sql-server

I have an existing database that I have used as a context for a project using Entity Framework in a multiple context project. The database contains several classes:
Market Message [Base Class]
MessageType300 [2nd level]
Meter [3rd level]
RegisterLevelInformation [4th level]
Using the code first from existing database tools it has created the following:
[Table("MarketMessage")]
public partial class MarketMessage
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public MarketMessage()
{
messageType300 = new HashSet<messageType300>();
messageType300S = new HashSet<messageType300S>();
messageType300W = new HashSet<messageType300W>();
messageType305 = new HashSet<messageType305>();
}
public int MarketMessageID { get; set; }
public DateTime CreatedOn { get; set; }
[Required]
[StringLength(4)]
public string messageType { get; set; }
[Required]
[StringLength(8)]
public string VersionNumber { get; set; }
public DateTime MarketTimestamp { get; set; }
[Required]
[StringLength(35)]
public string TxRefNbr { get; set; }
[Required]
[StringLength(3)]
public string Sender { get; set; }
[Required]
[StringLength(3)]
public string Recipient { get; set; }
[StringLength(10)]
public string alertFlag { get; set; }
[StringLength(50)]
public string fileName { get; set; }
public bool IsDeleted { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<messageType300> messageType300 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<messageType300S> messageType300S { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<messageType300W> messageType300W { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<messageType305> messageType305 { get; set; }
}
public partial class messageType300
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public messageType300()
{
Meter = new HashSet<Meter>();
UsageFactor = new HashSet<UsageFactor>();
}
public int messageType300ID { get; set; }
public int MarketMessageID { get; set; }
[Required]
[StringLength(11)]
public string MPRN { get; set; }
[StringLength(35)]
public string MPBR { get; set; }
[Required]
[StringLength(35)]
public string NetworkReferenceNumber { get; set; }
[Required]
[StringLength(3)]
public string LoadProfileCode { get; set; }
[Required]
[StringLength(4)]
public string DUoSGroup { get; set; }
[Required]
[StringLength(2)]
public string MeterPointStatusCode { get; set; }
public DateTime ReadDate { get; set; }
public virtual MarketMessage MarketMessage { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Meter> Meter { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<UsageFactor> UsageFactor { get; set; }
}
[Table("Meter")]
public partial class Meter
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Meter()
{
RegisterLevelInformation = new HashSet<RegisterLevelInformation>();
}
public int MeterID { get; set; }
[StringLength(15)]
public string MeterCategoryCode { get; set; }
[Required]
[StringLength(9)]
public string SerialNumber { get; set; }
[StringLength(3)]
public string MeterLocationCode { get; set; }
public int? MessageType300ID { get; set; }
public int? MessageType300SID { get; set; }
public int? MessageType300WID { get; set; }
public int? MessageType303RID { get; set; }
public int? MessageType305ID { get; set; }
public int? MessageType306ID { get; set; }
public int? MessageType306WID { get; set; }
public int? MessageType307ID { get; set; }
public int? MessageType307WID { get; set; }
public int? MessageType310ID { get; set; }
public int? MessageType310WID { get; set; }
public int? MessageType320ID { get; set; }
public int? MessageType320WID { get; set; }
public int? MessageType341ID { get; set; }
public int? MessageType342ID { get; set; }
public virtual messageType300 messageType300 { get; set; }
public virtual messageType300S messageType300S { get; set; }
public virtual messageType300W messageType300W { get; set; }
public virtual messageType305 messageType305 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<RegisterLevelInformation> RegisterLevelInformation { get; set; }
}
[Table("RegisterLevelInformation")]
public partial class RegisterLevelInformation
{
public int RegisterLevelInformationID { get; set; }
[Required]
[StringLength(3)]
public string MeterRegisterSequence { get; set; }
[Required]
[StringLength(10)]
public string TimeslotCode { get; set; }
[Required]
[StringLength(3)]
public string UOM_Code { get; set; }
public decimal MeterMultiplier { get; set; }
public decimal ReadingValue { get; set; }
[Required]
[StringLength(2)]
public string ReadReasonCode { get; set; }
[Required]
[StringLength(2)]
public string ReadTypeCode { get; set; }
public DateTime? PreviousReadDate { get; set; }
public decimal Consumption { get; set; }
public decimal EstimatedConsumption { get; set; }
[StringLength(4)]
public string ReadStatusCode { get; set; }
[StringLength(2)]
public string RegisterTypeCode { get; set; }
[StringLength(1)]
public string PostDecimalDetails { get; set; }
[StringLength(2)]
public string PreDecimalDetails { get; set; }
public int? MeterID { get; set; }
public int? RemovedMeterRegisterID { get; set; }
public int? NewMeterRegisterID { get; set; }
public int? RetainedMeterRegisterID { get; set; }
public virtual Meter Meter { get; set; }
}
How can I call the marketmessage and the related children including messagetype300, meter, and register level information data?
In the original database I am able to join the table together using a SQL query as follows:
select
MarketTimestamp, TxRefNbr, Sender, Recipient, MPRN,
NetworkReferenceNumber, LoadProfileCode, DUoSGroup,
MeterPointStatusCode, ReadDate, SerialNumber,
MeterRegisterSequence, TimeslotCode, UOM_Code, MeterMultiplier,
ReadingValue, ReadReasonCode, ReadTypeCode, PreviousReadDate,
Consumption, EstimatedConsumption, ReadStatusCode, RegisterTypeCode
from
marketmessage as a
inner join
messagetype300 as b on a.MarketMessageID = b.MarketMessageID
inner join
Meter as c on b.messageType300ID = c.MessageType300ID
inner join
RegisterLevelInformation as d on c.MeterID = d.MeterID
where
DUoSGroup = 'T021'
and TimeslotCode = 'UNR'
order by
MarketTimestamp desc
I have attempted to join this in the following way but I am unable to access the properties of either the meters or the register level information from my view:
var test = db.MarketMessage.Where(m => m.messageType == "300S")
.Include(m => m.messageType300S.Select(mt => mt.Meter))
.ToList();
I am attempting the following:
<td>
#Html.DisplayFor(modelItem => item.Recipient)
</td>
<td>
#Html.DisplayFor(modelItem => item.alertFlag)
</td>
<td>
#Html.DisplayFor(modelItem => item.fileName)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsDeleted)
</td>
<td>
#foreach (var m in item.messageType300S.Select(m => m.Meter).FirstOrDefault())
{
#Html.Display(m.SerialNumber)
}
</td>
Obviously I dont really want to be iterating the meters in this manner although this is not even displaying the serial number despite it being found when I am debugging so lost as to what is going on

Related

Entities with problems and limitations

I have these entities:
public class Project : Base
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public ProjectStatus CurrentStatus { get; set; } = ProjectStatus.New;
public List<StatusHistory>? StatusHistories { get; set; }
public Team? Team { get; set; }
public int? TeamId { get; set; }
// public ProgressTrackerValue trackerValue { get; set; }
public List<AttachedFile> AttachedFiles { get; set; }
}
public class Task : Base
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime? EstimatedDueDate { get; set; }
public DateTime? ActualDueDate { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; } // ?? End DATE same as ActualDueDate
public TaskStatus CurrentStatus { get; set; } = TaskStatus.Draft;
public int ProjectId { get; set; }
public Project Project { get; set; }
public List<StatusHistory> StatusHistories { get; set; }
public TaskType TaskType { get; set; }
public TaskPriority Priority { get; set; }
public float ? DurationProgress { get; set; }
public List<AttachedFile> AttachedFiles { get; set; }
}
public class Team : Base
{
public string TeamLeaderId { get; set; }
public List<TeamMember>? TeamMembers { get; set; }
public virtual Project Project { get; set; }
}
public class AttachedFile : Base
{
public string OriginalFileName { get; set; }
public string FileName { get; set; }
public string MimeType { get; set; }
public string FileType { get; set; }
public string OwnerType { get; set; }
public int OwnerId {get; set;}
public string FilePath { get; set; }
public long FileSize { get; set; }
}
public class Comment : Base
{
public string Content { get; set; }
public int? ParentCommentId { get; set; }
public List<Comment>? Replies { get; private set; }
public Task Task { get; set; }
public int taskId { get; set; }
public List<AttachedFile>? AttachedFiles { get; set; }
}
public class StatusHistory : Base
{
public string OwnerType { get; set; }
public int OwnerId {get; set;}
public string State { get; set; }
}
public class TaskEmployee : Base
{
public int TaskId { get; set; }
public Task Task { get; set; }
public string EmployeeId { get; set; }
}
public class TeamMember : Base
{
public string UserId { get; set; }
}
What can I do to improve the above entities? Any suggestions.
Also there is UserId,EmployeeId,TeamLeaderId.... all of these supposed to be FK to IdentityUser but this project is isolated from Identity and i can't find a way to link them together. if there is a suggestion on how could I make such relationship in EFCore. (I could make relationship manually but I can't put navigation properties for Identity inside these entities thus not benefiting from EFCore).
Finally there is OwnerType, OwnerId, for example in the AttachedFile entity the attached file could be related to Project, Task, Comment. So I will store the type and id for them in these fields, the problem however that I will not benefit form EF Core functionality this way. For example: I must write SQL manually for every query.
currently the schema look like this:
enter image description here

Error on update-database efcore asp.net core

namespace LoopSquad.Core.Entities.Addresses
{
public class Address
{
public int AddressId { get; set; }
public string NoName { get; set; }
public string AddressL1 { get; set; }
public string AddressL2 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
[ForeignKey("Customer")]
public int CustomerId { get; set; }
public Customers.Customer Customer { get; set; }
public ICollection<Jobs.Job> Jobs { get; set; }
}
}
namespace LoopSquad.Core.Entities.Customers
{
public class Customer
{
[Key]
public int CustomerId { get; set; }
public string CompanyName { get; set; }
[ForeignKey("FKCustomerType")]
public int CustomerTypeId { get; set; }
public CustomerType CustomerType { get; set; }
public ICollection<Addresses.Address> Addresses { get; set; }
}
}
namespace LoopSquad.Core.Entities.Jobs
{
public class Job
{
[Key]
public int JobId { get; set; }
[ForeignKey("FKCustomer")]
public int CustomerId { get; set; }
public Customers.Customer Customer { get; set; }
[ForeignKey("FKAddress")]
public int AddressId { get; set; }
public Addresses.Address Address { get; set; }
public DateTime BookedDateTime { get; set; }
public DateTime CreatedDateTime { get; set; }
[ForeignKey("FKUser")]
public int UserId { get; set; }
public Users.ApplicationUser ApplicationUser { get; set; }
[ForeignKey("FRoomLayout")]
public int RoomLayoutId { get; set; }
public RoomLayout RoomLayout { get; set; }
[ForeignKey("FKJobType")]
public int JobTypeId { get; set; }
public JobType JobType { get; set; }
[ForeignKey("FKLoopType")]
public int loopTypeId { get; set; }
public LoopType LoopType { get; set; }
[ForeignKey("FKJobStatus")]
public int JobStatusId { get; set; }
public JobStatus JobStatus { get; set; }
}
}
I reproduce your problem and it is because you enable cascade delete by default which will result in cycles for your relationships.
Try to disable it using OnDelete(DeleteBehavior.Restrict) in dbcontext, for example
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Address> Addresses { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Job> Jobs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Job>().HasOne(p => p.Customer)
.WithMany()
.HasForeignKey(p => p.CustomerId)
.OnDelete(DeleteBehavior.Restrict);
}
}
Refer to https://learn.microsoft.com/en-us/ef/core/saving/cascade-delete

how to combine multiple models into one viewmodel based on a condition ? (WPF)

I have the following three models:
namespace Company.Model {
class Country
{
public int CountryId { get; set; }
public string CountryName { get; set; }
} }
and
namespace Company.Model
{
class Employee
{
public int EmployeeId { get; set; }
public string EmployeeFirstName { get; set; }
public string EmployeeMiddleName { get; set; }
public string EmployeeLastName { get; set; }
public DateTime? EmployeeDOB { get; set; }
public char? EmployeeGender { get; set; }
public string EmployeeAddress { get; set; }
public int? EmployeeContactNumber { get; set; }
public string EmployeeEmailID { get; set; }
public DateTime? EmployeeJoiningDate { get; set; }
public DateTime? EmployeeConfirmationDate { get; set; }
public DateTime? EmployeeExpectedInTime { get; set; }
public DateTime? EmployeeExpectedOutTime { get; set; }
public bool? EmployeeIsResigned { get; set; }
public double? EmployeeSalary { get; set; }
public string EmployeeDesignation { get; set; }
public int? DepartmentId { get; set; }
public int? CountryId { get; set; }
}
}
and
namespace Company.Model
{
class Department
{
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
}
}
Now I need to combine all three into one viewmodel, based on the condition that Employee.CountryId=Country.CountrId and Employee.DepartmentId=Department.DepartmentId.
I basically want a join on the tables, so as to get country name and department name of each employee.

Invalid object name 'dbo.customers1'

I'm getting the error "Invalid object name 'dbo.customers1'" on my view...
#foreach (var item in Model)
{
<tr>
<td>#item.orderid</td>
<td>#item.customer.firstname</td>
I have the ViewModel classes...
public class orders
{
[Key]
public int orderid { get; set; }
public System.DateTime createdate { get; set; }
public string createdby { get; set; }
public Nullable<int> statusid { get; set; }
public Nullable<System.DateTime> pickup { get; set; }
public Nullable<System.DateTime> dropoff { get; set; }
public Nullable<System.DateTime> scheduledout { get; set; }
public Nullable<System.DateTime> scheduledin { get; set; }
public bool instorepickup { get; set; }
public string paymenttype { get; set; }
public System.DateTime reservationstart { get; set; }
public System.DateTime reservationend { get; set; }
public bool morningpickup { get; set; }
public Nullable<int> customerid { get; set; }
public string notes { get; set; }
public string shippingtype { get; set; }
public Nullable<decimal> shippingestimate { get; set; }
public virtual customer customer { get; set; }
public virtual ICollection<invoice> invoices { get; set; }
public virtual orderstatuses orderstatuses { get; set; }
public virtual ICollection<serialorders> serialorders { get; set; }
}
and
public class customers
{
[Key]
public int customerid { get; set; }
public System.DateTime createdate { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
[Required]
public string billingaddress1 { get; set; }
public string billingaddress2 { get; set; }
[Required]
public string billingcity { get; set; }
public string billingstate { get; set; }
[Required]
public string billingzip { get; set; }
[Required]
public string billingcountry { get; set; }
public string phone { get; set; }
[Required]
public string email { get; set; }
[Required]
public string shippingaddress1 { get; set; }
public string shippingaddress2 { get; set; }
[Required]
public string shippingcity { get; set; }
public string shippingstate { get; set; }
[Required]
public string shippingzip { get; set; }
[Required]
public string shippingcountry { get; set; }
public bool goodstanding { get; set; }
public string userid { get; set; }
public Nullable<DateTime> insuranceexp { get; set; }
public virtual ICollection<invoice> invoices { get; set; }
public virtual ICollection<order> orders { get; set; }
}
this is my model...
And I have a data access layer...
public DbSet<tvc.viewModels.orders> orders { get; set; }
public DbSet<tvc.viewModels.customers> customers { get; set; }
The error is pretty straight-forward. There's no dbo.customers1 table in your database. As to why, there's really not enough information here to say, but the most likely causes are:
You're using Database First or Code First with an existing database, and your entities are out of sync with the database.
You're using Code First, don't have migrations enabled, and you've made a change to either your entities or your database. Again, out of sync.
You've specified an explicit table name, either via the Table attribute or fluent config, that doesn't exist. Either way, change either the explicit table name to what it should be or rename your database table so it matches.
There was an oversight in my ViewModel. I was pointing customer, which is the name of the database table and the model class, rather than the viewmodel class which is customers (with an s).

How to generate a unique GUID when creating a new object in Entity Framework 5?

I've similar questions that refer to this annotation to solve their problem:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
However, applying this to my relevant Entity Model does nothing.
When I call the .Add() method, it inserts the GUID as 00000000-0000-0000-0000-000000000000.
As you can see, the annotation I mentioned is present in the model:
using System;
using System.Collections.Generic;
public partial class Event
{
[System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public System.Guid ID { get; set; }
public int AccountID { get; set; }
public string ExternalID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Location { get; set; }
public Nullable<System.DateTime> StartTime { get; set; }
public Nullable<System.DateTime> EndTime { get; set; }
public Nullable<bool> AllDay { get; set; }
public Nullable<System.Guid> ImageData { get; set; }
public string ImageUrl { get; set; }
public virtual Account Account { get; set; }
public virtual FetchedFile FetchedFile { get; set; }
}
How can I generate a unique GUID upon inserting a new Entity Object?
You can always initialize the Guid in a constructor.
public partial class Event
{
public Event()
{
ID = Guid.NewGuid();
}
public System.Guid ID { get; set; }
public int AccountID { get; set; }
public string ExternalID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Location { get; set; }
public Nullable<System.DateTime> StartTime { get; set; }
public Nullable<System.DateTime> EndTime { get; set; }
public Nullable<bool> AllDay { get; set; }
public Nullable<System.Guid> ImageData { get; set; }
public string ImageUrl { get; set; }
public virtual Account Account { get; set; }
public virtual FetchedFile FetchedFile { get; set; }
}

Resources