Cycles or multiple cascade paths - c#

I have the following datamodel and its associated model classes. I have been removing dependencies to get it right, but I keep on getting this error.
Datamodel
I can't find out why there is a cascading path in the model. I am afraid I will not be able to reduce the dependencies.
Model Classes
public class DataFormat
{
public int DataFormatID { get; set; }
[Display (Name = "Data Format Name")]
[Remote("DuplicateFormatName", "DataFormats", HttpMethod = "POST", ErrorMessage = "Data Format Name already Exists")]
public string FormatName { get; set; }
[Display (Name = "Data Format Type")]
public string FormatType { get; set; }
[Display (Name = "Precision Digits")]
public string PrecisionDigits { get; set; }
[Display (Name = "Scaling Digits")]
public string ScalingDigits { get; set; }
[Display (Name = "Description in German")]
public string DescriptionDE { get; set; }
[Display (Name = "Description in English")]
public string DescriptionEN { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set;}
public string ModifiedBy { get; set; }
public virtual ICollection<TcSet> TcSets { get; set; }
}
public class Lsystem
{
public int LsystemID { get; set; }
[Display (Name = "System Name") ]
[Remote("DuplicateSystemName", "Lsystems", HttpMethod = "POST", ErrorMessage = "System Name already Exists")]
public string LsystemName { get; set; }
[Display (Name = "Material Number")]
public string MaterialNumber { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
[Display(Name = "Description in English")]
public string DescriptionEN { get; set; }
[Display(Name = "Description in German")]
public string DescriptionDE { get; set; }
public int LsystemFamilyID { get; set; }
public virtual LsystemFamily LsystemFamily { get; set; }
public virtual ICollection<Option> Options { get; set; }
}
public class LsystemFamily
{
public int LsystemFamilyID { get; set; }
[Display (Name = "Family Name")]
[Remote("DuplicateFamilyName","LsystemFamilies",HttpMethod = "POST",ErrorMessage= "System Family Name already Exists")]
public string FamilyName { get; set; }
public int LsystemCount { get; set; }
[Display ( Name = "Description in English")]
public string DescriptionEN { get; set; }
[Display (Name = "Description in German")]
public string DescriptionDE { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public virtual ICollection<Lsystem> Lsystems { get; set; }
}
public class Option
{
public int OptionID { get; set;}
[Display (Name = "Option Type")]
public string OptionName { get; set; }
[Display (Name ="Description in English")]
public string DescriptionEN { get; set; }
[Display(Name = "Description in German")]
public string DescriptionDE { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public int TechnicalCharacteristicID { get; set; }
public int LsystemID { get; set; }
public virtual ICollection<OptionValue> OptionValues { get; set; }
public virtual TechnicalCharacteristic TechnicalCharacteristic { get; set; }
public virtual Lsystem Lsystem { get; set; }
// public virtual ICollection< SetValue> SetValue { get; set; }
}
public class OptionValue
{
public int OptionValueID { get; set; }
[Display(Name = "Option Value")]
public string OptionVal { get; set; }
public int OptionID { get; set; }
// public int SetValueID { get; set; }
public virtual Option Option { get; set; }
public virtual ICollection< SetValue> SetValue { get; set; }
}
public class SetValue
{
public int SetValueID { get; set; }
[Display(Name = "Value")]
public string Value { get; set; }
[Display(Name="Internal")]
public bool Status { get; set; }
//public int LsystemID { get; set; }
//public int OptionID { get; set; }
public int TcSetID { get; set; }
public int OptionValueID { get; set; }
//public virtual Lsystem Lsystem { get; set; }
//public virtual Option Option { get; set; }
public virtual OptionValue OptionValue { get; set; }
public virtual TcSet TcSet { get; set; }
}
public class TcSet
{
public int TcSetID { get; set; }
[Display (Name = "Technical characteristic Property name")]
public string SetName { get; set; }
[Display(Name = "PhysicalUnit")]
public string PhysicalUnit { get; set; }
[Display (Name = "Data Usage")]
public DataUsage DataUsage { get; set; }
[Display (Name = "Data Status")]
public DataStatus DataStatus { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
[Display (Name = "Description in German")]
public string DescriptionDE { get; set; }
[Display (Name = "Description in English")]
public string DescriptionEN { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public int TechnicalCharacteristicID { get; set; }
public int DataFormatID { get; set; }
public virtual ICollection<SetValue> SetValues { get; set; }
public virtual DataFormat DataFormat { get; set; }
public virtual TechnicalCharacteristic TechnicalCharacteristic { get; set; }
}
public class TechnicalCharacteristic
{
public int TechnicalCharacteristicID { get; set; }
[Display (Name = "Technical Characteristic Name")]
public string TCName { get; set; }
[Display (Name = "Description in English")]
public string DescriptionEN { get; set; }
[Display (Name = "Description in German")]
public string DescriptionDE { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public virtual ICollection<TcSet> TcSets { get; set; }
//public virtual ICollection<Option> Options { get; set; }
}
Now my error is between the tables Options and technicalCharacteristics. I had the error previosly with LSystem and SetVal & Options.
What can be the workaround to get the task right?
I have not tried fluent APIs.

Here is another way you can do the same AND have a technicalChareristic to be required. I did this last week with one of my own models. Sorry it toook so long to come up with a reply. (Do the same with the other files.)
In your Context file override the following method...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Option>()
.HasRequired(x => x.TechnicalCharacteristic)
.WithMany(y => y.Options)
.HasForeignKey(a => a.TechnicalCharacteristicID)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
Where the models are...
public class Option
{
public int OptionID { get; set; }
[Display(Name = "Option Type")]
public string OptionName { get; set; }
[Display(Name = "Description in English")]
public string DescriptionEN { get; set; }
[Display(Name = "Description in German")]
public string DescriptionDE { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public int LsystemID { get; set; }
public virtual ICollection<OptionValue> OptionValues { get; set; }
public int TechnicalCharacteristicID { get; set; }
public virtual TechnicalCharacteristic TechnicalCharacteristic { get; set; }
public virtual Lsystem Lsystem { get; set; }
// public virtual ICollection< SetValue> SetValue { get; set; }
DateTime d = new DateTime();
}
public class TechnicalCharacteristic
{
public int TechnicalCharacteristicID { get; set; }
[Display(Name = "Technical Characteristic Name")]
public string TCName { get; set; }
[Display(Name = "Description in English")]
public string DescriptionEN { get; set; }
[Display(Name = "Description in German")]
public string DescriptionDE { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public virtual ICollection<TcSet> TcSets { get; set; }
public virtual ICollection<Option> Options { get; set; }
}
I hope this helps.

I believe your error is coming because EntityFramework cannot handle the null state of your TechnicalCharacteristicID in the Option class. If you have no problem in TechnicalCharacteristic being null, do the following in your option class. It should get rid of your error:
public int? TechnicalCharacteristicID { get; set; }
that is, your option class will become...
public class Option
{
public int OptionID { get; set; }
[Display(Name = "Option Type")]
public string OptionName { get; set; }
[Display(Name = "Description in English")]
public string DescriptionEN { get; set; }
[Display(Name = "Description in German")]
public string DescriptionDE { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public int LsystemID { get; set; }
public virtual ICollection<OptionValue> OptionValues { get; set; }
public int? TechnicalCharacteristicID { get; set; }
public virtual TechnicalCharacteristic TechnicalCharacteristic { get; set; }
public virtual Lsystem Lsystem { get; set; }
// public virtual ICollection< SetValue> SetValue { get; set; }
}
Do the same with other errant tables. I hope this answers your question! Good luck.

Related

Null value in query using Select statement

I want to create a query that will return an AgencyContractData object containing a DocumentDto object, but it may be that the original object does not contain a foreign key on the Document. I can't use ternary operator in an Entity-Framwork LINQ query. How it is possible to implement it (Required that select be converted to sql query)?
var contractList = await query
.Select(contract => new AgencyContractData
{
ContractId = contract.Id,
ContractNumber = contract.ContractNumber,
CustomerId = contract.CustomerId,
CustomerName = contract.CustomerName,
Group = contract.Group,
CommodityType = contract.CommodityType,
SupplierName = contract.SupplierName,
StartDate = contract.StartDate,
EndDate = contract.EndDate,
ExecutionDate = contract.ExecutionDate,
ContractUnit = contract.ContractUnit,
Comment = contract.Comment,
Pricing = contract.Pricing,
SecondaryCustomerName = contract.SecondaryCustomerName,
ContractType = contract.ContractType,
AnnualVolume = contract.AnnualVolume,
Document = new DocumentDto
{
DocumentId = contract.Document.Id,
CounterPartyId = contract.Document.CounterPartyId,
FilePath = contract.Document.FilePath,
DocumentTitle = contract.Document.DocumentTitle,
IsCustomerUpload = contract.Document.IsCustomerUpload,
DocumentBytes = null
},
DocumentName = contract.DocumentName,
ContractNumberInt = contract.ContractNumberInt,
ContractNumberString = contract.ContractNumberString,
MsaBaseNumber = contract.MsaBaseNumber,
NotificationDays = contract.NotificationInDays,
State = contract.State,
CreatedOn = contract.CreatedOn,
CreatedBy = contract.CreatedBy,
ModifiedOn = contract.ModifiedOn,
ModifiedBy = contract.ModifiedBy,
It is the AgencyContract entity:
public class Contract : IEntity<long>
{
public long Id { get; set; }
public string ContractNumber { get; set; }
public long? ContractUnitId { get; set; }
public int? NumPricePeriods { get; set; }
public double? Tolerance { get; set; }
public ContractTypeEnum? ContractType { get; set; }
public ContractTolerancePeriodEnum? ContractTolerancePeriod { get; set; }
public bool IsRelyContract { get; set; }
public int TermsEndNoticeDays { get; set; }
public bool IsProrated { get; set; }
public bool IsContinuation { get; set; }
public long SupplierId { get; set; }
public long? DocumentId { get; set; }
public long? BrokerId { get; set; }
public BillTypeEnum? BillType { get; set; }
public string ExternalId { get; set; }
#region Navigation Properties
public virtual Supplier Supplier { get; set; }
public virtual Broker Broker { get; set; }
public virtual ContractUnit ContractUnit { get; set; }
public virtual Account Account { get; set; }
public virtual List<UsnAccountToContract> UsnAccountToContracts { get; set; }
public virtual List<ProviderLookup> ProviderLookups { get; set; }
public virtual List<ContractNotification> ContractNotifications { get; set; }
public virtual List<ContractVolume> ContractVolumes { get; set; }
public virtual Document Document { get; set; }
#endregion
And I want to make a AgencyContractData object using Select:
public class AgencyContractData
{
public int? AnnualVolume { get; set; }
public string Comment { get; set; }
public AgencyCommodityTypeEnum CommodityType { get; set; }
public long ContractId { get; set; }
public string ContractNumber { get; set; }
public long? ContractNumberInt { get; set; }
public string ContractNumberString { get; set; }
public int? ContractReportLevelByGlobalSearch { get; set; }
public AgencyContractTypeEnum ContractType { get; set; }
public AgencyContractUnitEnum ContractUnit { get; set; }
public Guid? CreatedBy { get; set; }
public DateTime? CreatedOn { get; set; }
public long? CustomerId { get; set; }
public string CustomerName { get; set; }
public string DocumentName { get; set; }
public DocumentDto Document { get; set; }
public DateTime? EndDate { get; set; }
public DateTime ExecutionDate { get; set; }
public string Group { get; set; }
public List<AgencyLocationData> Locations { get; set; }
public Guid? LockedBy { get; set; }
public DateTime? LockedOn { get; set; }
public string Md5Hash { get; set; }
public Guid? ModifiedBy { get; set; }
public DateTime? ModifiedOn { get; set; }
public string MsaBaseNumber { get; set; }
public int? NotificationDays { get; set; }
public DateTime? NotificationSentOn { get; set; }
public string Pricing { get; set; }
public string SecondaryCustomerName { get; set; }
public int Sites { get; set; }
public DateTime StartDate { get; set; }
public string State { get; set; }
public string Status { get; set; }
public string SupplierName { get; set; }

EF Core API how to remove the Required value

How to remove the Required value of Remarks property I'm not setting the value as required, when I run the swagger the Remarks parameter set as required here is my Entities
public class FixedAsset
{
public long FixedAssetMovementEntitiesId { get; set; }
[Required]
public string Type { get; set; }
[Required]
public string EmployeeId { get; set; }
[Required]
public string EmployeeName { get; set; }
[Required]
public string FixedAssetId { get; set; }
[Required]
public string FixedAssetDescription { get; set; }
public int ServiceLife { get; set; }
[Required]
public string Company { get; set; }
public string Remarks { get; set; }
public IsReturnedEnum IsReturned { get; set; }
}
My Base DataContracts inherited from Interface
public class BaseFixedAssetMovement : InterfaceFixedAssetMovement
{
[Required]
public string Type { get; set; }
[Required]
public string EmployeeId { get; set; }
[Required]
public string EmployeeName { get; set; }
[Required]
public string FixedAssetId { get; set; }
[Required]
public string FixedAssetDescription { get; set; }
public int ServiceLife { get; set; }
[Required]
public string Company { get; set; }
public string Remarks { get; set; }
public IsReturnedEnum IsReturned { get; set; }
}

SQL to Entity Framework, inner SELECT with multiple JOINs

I have the following SQL query that I need to rewrite to Entity Framework with navigation properties. Basically, and Employee has a number of tasks that someone can volunteer to do. I'm trying to find all employees that have at least one volunteer assigned to any task.
SELECT j.noTasks, e.*
FROM Employee e
LEFT JOIN
(SELECT e.id, COUNT(vt.TaskId) as "noTasks"
FROM Employee e
LEFT JOIN Task t on e.id = t.EmployeeId
LEFT JOIN VolunteerTask vt on vt.TaskId = t.id
GROUP BY e.id) j
ON e.id = j.id AND noTasks > 0
The troubling part is the inner SELECT. I've read the documentation, but I'm having difficulties understanding it.
Employee class:
public partial class Employee : IEntity
{
public int id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[StringLength(100)]
public string WorkPlace { get; set; }
public int EmployeeTypeId { get; set; }
[Required]
[StringLength(11)]
public string OrganizationNumber { get; set; }
[StringLength(20)]
public string Telephone { get; set; }
[Required]
[StringLength(100)]
public string StreetAddress { get; set; }
[StringLength(200)]
public string CoAddress { get; set; }
[Required]
[StringLength(20)]
public string ZipCode { get; set; }
[StringLength(200)]
public string City { get; set; }
[StringLength(200)]
public string HomePage { get; set; }
[Required]
[StringLength(200)]
public string ContactPerson { get; set; }
[StringLength(30)]
public string ContactPhone { get; set; }
[StringLength(30)]
public string ContactPhone2 { get; set; }
[StringLength(200)]
public string ContactEmailAddress { get; set; }
public DateTime RegisteredDate { get; set; }
public virtual EmployeeType EmployeeType { get; set; }
[Required]
public UserStatus Status { get; set; }
public string ImageFileName { get; set; }
}
Task class:
public partial class Task : IEntity
{
public Task()
{
VoluntaryTasks = new HashSet<VoluntaryTask>();
TaskInterest = new HashSet<TaskInterest>();
TaskCalendarItems = new HashSet<TaskCalendarItem>();
}
public int id { get; set; }
[StringLength(100)]
public string Name { get; set; }
public int EmployeeId { get; set; }
public int AreaId { get; set; }
[Column(TypeName = "ntext")]
public string Description { get; set; }
public int NoOfVolunteers { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? PublicationDate { get; set; }
public DateTime EndDate { get; set; }
[Required]
[StringLength(200)]
public string ContactPerson { get; set; }
[Required]
[StringLength(30)]
public string ContactTelephone { get; set; }
[StringLength(30)]
public string ContactTelephone2 { get; set; }
[StringLength(100)]
public string EmailAddress { get; set; }
public bool isPublished { get; set; }
public bool NotificationMailSent { get; set; }
public double? Latitude { get; set; }
public double? Longitude { get; set; }
public int Priority { get; set; }
public RecordStatus RecordStatus { get; set; }
public virtual Area Area { get; set; }
public string LocationDescription {get; set;}
public virtual Employee Employee { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<VoluntaryTask> VoluntaryTasks { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<TaskInterest> TaskInterest { get; set; }
public virtual ICollection<TaskLanguageSkill> TaskLanguageSkills { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<TaskCalendarItem> TaskCalendarItems { get; set; }
}
VoluntaryTask class:
public partial class VoluntaryTask
{
//[Key]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int VoluntaryId { get; set; }
//[Key]
[Column(Order = 1)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int TaskId { get; set; }
//[Key]
public VoluntaryTaskStatus Status { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public virtual Task Task { get; set; }
public virtual Voluntary Voluntary { get; set; }
}

handling circular references when saving(post)

I am stuck with an error i can't figure out. I have a complex model with several circular references. I have tried everything i know to handle them but i am still getting a internal server error (code 500) when i attempt saving.
Below are the models and controllers:
public partial class Event
{
public Event()
{
Recurrences = new HashSet<Recurrence>();
}
public int Id { get; set; }
[Required]
[StringLength(150)]
public string Title { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
[StringLength(128)]
public string CreatedBy { get; set; }
[StringLength(128)]
public string UpdatedBy { get; set; }
public ICollection<Recurrence> Recurrences { get; set; }
}
public partial class Recurrence
{
public Recurrence()
{
AspNetUsers = new HashSet<AspNetUser>();
}
public int Id { get; set; }
public int EventId { get; set; }
[Column(TypeName = "date")]
public DateTime StartDate { get; set; }
[Column(TypeName = "date")]
public DateTime? EndDate { get; set; }
public bool? AllDay { get; set; }
public TimeSpan? StartTime { get; set; }
public TimeSpan? EndTime { get; set; }
[StringLength(500)]
public string Venue { get; set; }
public double? Longitude { get; set; }
public double? Latitude { get; set; }
public int? RecurrenceInterval { get; set; }
public bool? ExcludeWeekends { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
[StringLength(128)]
public string CreatedBy { get; set; }
[StringLength(128)]
public string UpdatedBy { get; set; }
public Event Event { get; set; }
public RecurrenceType RecurrenceType { get; set; }
public ICollection<AspNetUser> AspNetUsers { get; set; }
}
public partial class AspNetUser
{
public AspNetUser()
{
Recurrences = new HashSet<Recurrence>();
}
public string Id { get; set; }
[StringLength(256)]
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public DateTime? LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
[Required]
[StringLength(256)]
public string UserName { get; set; }
public ICollection<Recurrence> Recurrences { get; set; }
}
public class EventDTO
{
public int Id { get; set; }
[Required]
[StringLength(150)]
public string Title { get; set; }
public int EventTypeId { get; set; }
[Column(TypeName = "date")]
public DateTime StartDate { get; set; }
[Column(TypeName = "date")]
public DateTime EndDate { get; set; }
public bool? AllDay { get; set; }
public TimeSpan? StartTime { get; set; }
public TimeSpan? EndTime { get; set; }
[StringLength(500)]
public string Venue { get; set; }
public double? Longitude { get; set; }
public double? Latitude { get; set; }
public int RecurrenceTypeId { get; set; }
public int? RecurrenceInterval { get; set; }
public bool? ExcludeWeekends { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
[StringLength(128)]
public string CreatedBy { get; set; }
[StringLength(128)]
public string UpdatedBy { get; set; }
public List<string> UserId { get; set; }
}
public async Task<IHttpActionResult> PostEvent(EventDTO #event)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Event newEvent = new Event();
newEvent.Title = #event.Title;
newEvent.EventTypeId = #event.EventTypeId;
newEvent.CreateDate = #event.CreateDate;
newEvent.UpdateDate = #event.UpdateDate;
newEvent.CreatedBy = #event.CreatedBy;
newEvent.UpdatedBy = #event.CreatedBy;
if (newEvent == null) {
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, "Error creating Event"));
}
Recurrence recurrence = new Recurrence();
recurrence.StartDate = #event.StartDate;
recurrence.EndDate = #event.EndDate;
recurrence.AllDay = #event.AllDay;
recurrence.StartTime = #event.StartTime;
recurrence.EndTime = #event.EndTime;
recurrence.Venue = #event.Venue;
recurrence.Longitude = #event.Longitude;
recurrence.Latitude = #event.Latitude;
recurrence.RecurrenceTypeId = #event.RecurrenceTypeId;
recurrence.RecurrenceInterval = #event.RecurrenceInterval;
recurrence.ExcludeWeekends = #event.ExcludeWeekends;
recurrence.CreateDate = #event.CreateDate;
recurrence.UpdateDate = #event.UpdateDate;
recurrence.CreatedBy = #event.CreatedBy;
recurrence.UpdatedBy = #event.CreatedBy;
if (recurrence == null)
{
throw new HttpResponseException(
Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, "Error creating recurrence"));
}
var users = db.AspNetUsers.Where(u => #event.UserId.Contains(u.Id));
foreach (var u in users)
recurrence.AspNetUsers.Add(u);
newEvent.Recurrences.Add(recurrence);
db.Events.Add(newEvent);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = #event.Id }, newEvent);
}
When i call the post method i get an internal error code 500 and an error message of "{$id=1, Message=An error has occurred}".

Complex relationship mappings in entity framework

I am building a reservation system. I have users in roles('admin', 'client', 'employee', 'student').
Each reservation must be associated with a user of role client, it might be assigned to user of role employee and might also be assigned to user of role student.
So in my reservation class I have properties of type User and I have marked them with [ForeignKey("AnytypeId")] attribute to hint EF for relations.
I have seen code like this at http://blog.stevensanderson.com/2011/01/28/mvcscaffolding-one-to-many-relationships/
public class Reservation
{
public int ReservationID
{
get;
set;
}
[Required(ErrorMessage="Please provide a valid date")]
public DateTime ReservationDate
{
get;
set;
}
public DateTime ReservationEnd { get; set; }
public DateTime EntryDate
{
get;
set;
}
public DateTime UpdatedOn
{
get;
set;
}
public decimal Ammount
{
get;
set;
}
public decimal? Discount { get; set; }
[DataType(DataType.MultilineText)]
public string ServiceDetails { get; set; }
[DataType(DataType.MultilineText)]
public string Remarks { get; set; }
public string VoucherNumber { get; set; }
public int ServiceID
{
get;
set;
}
public Service Service
{
get;
set;
}
public string EmployeeId { get; set; }
[ForeignKey("EmployeeId")]
public User Employee { get; set; }
public string ClientId { get; set; }
[ForeignKey("ClientId")]
public User Client { get; set; }
public string StudentId { get; set; }
[ForeignKey("StudentId")]
public User Student { get; set; }
}
public class User
{
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
//public Guid UserId { get; set; }
[Key]
[Required(ErrorMessage = "User Name is required")]
[Display(Name = "User Name")]
[MaxLength(100)]
public string UserName { get; set; }
[Required]
[MaxLength(64)]
public byte[] PasswordHash { get; set; }
[Required]
[MaxLength(128)]
public byte[] PasswordSalt { get; set; }
[Required(ErrorMessage = "Email is required")]
[DataType(DataType.EmailAddress)]
[MaxLength(200)]
public string Email { get; set; }
[MaxLength(200)]
public string Comment { get; set; }
[Display(Name = "Approved?")]
public bool IsApproved { get; set; }
[Display(Name = "Crate Date")]
public DateTime DateCreated { get; set; }
[Display(Name = "Last Login Date")]
public DateTime? DateLastLogin { get; set; }
[Display(Name = "Last Activity Date")]
public DateTime? DateLastActivity { get; set; }
[Display(Name = "Last Password Change Date")]
public DateTime DateLastPasswordChange { get; set; }
public string address { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Phone { get; set; }
public bool? IsActive { get; set; }
public int? ClientTypeID { get; set; }
public virtual ClientType ClientType { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public DateTime? PackageValidity { get; set; }
public virtual ICollection<Reservation> Reservations { get; set; }
}
public class UserMap : EntityTypeConfiguration<User>
{
public UserMap()
{
this.HasMany(u => u.Roles)
.WithMany(r => r.Users)
.Map(m =>
{
m.ToTable("RoleMemberships");
m.MapLeftKey("Username");
m.MapRightKey("RoleName");
});
}
}
Now as I run my mvc3 EF code first app database created for me on the fly with following ERD and edmx model.
Now few problems that I am having:
1. When I am listing all the users of role clients their reservation property is showing always 0 even if their are reservations available in database.
2. If I am trying to delete a user of role client who have reservation in database I get following error.
The DELETE statement conflicted with the REFERENCE constraint "Reservation_Client". The conflict occurred in database "CRSDB", table "dbo.Reservations", column 'ClientId'.
The statement has been terminated.
I checked the realtions in ERD and edmx model their is no cascade delete applied to them. How can I instruct EF to delete all the reservations when deleting user of role client but not for users of role employee or student.
This code does the trick
public class Reservation
{
public int ReservationID
{
get;
set;
}
[Required(ErrorMessage="Please provide a valid date")]
public DateTime ReservationDate
{
get;
set;
}
public DateTime ReservationEnd { get; set; }
public DateTime EntryDate
{
get;
set;
}
public DateTime UpdatedOn
{
get;
set;
}
public decimal Ammount
{
get;
set;
}
public decimal? Discount { get; set; }
[DataType(DataType.MultilineText)]
public string ServiceDetails { get; set; }
[DataType(DataType.MultilineText)]
public string Remarks { get; set; }
public String PaymentMethod { get; set; }
public string VoucherNumber { get; set; }
public int ServiceID
{
get;
set;
}
public virtual Service Service
{
get;
set;
}
public string EmployeeID { get; set; }
[ForeignKey("EmployeeID")]
public virtual User Employee { get; set; }
public string ClientID { get; set; }
[ForeignKey("ClientID")]
public virtual User Client { get; set; }
public string StudentID { get; set; }
[ForeignKey("StudentID")]
public virtual User Student { get; set; }
}
public class ReservationMap : EntityTypeConfiguration<Reservation>
{
public ReservationMap()
{
this.HasOptional(r => r.Client).WithMany().WillCascadeOnDelete(true);
this.HasOptional(r => r.Employee).WithMany().WillCascadeOnDelete(false);
this.HasOptional(r=>r.Student).WithMany().WillCascadeOnDelete(false);
}
}

Categories

Resources