I'm trying to create the following object for my DB (CodeFirst),
And i have the following problem:
when i try to add new one or many object to a new srevice provider slots (as follows:)
ServiceProviderSlots slot = new ServiceProviderSlots();
slot.ServiceProviderID = 1;
slot.SlotServices.Add(new ServiceProviderServices() { ServiceProviderServiceID = 1 });
ctx.ServiceProviderSlots.Add(slot);
I get an error, because i'm not creating a new object, and i'm missing foreign keys, but i wish to use data which already exists on that table.
ERROR:
{"The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_dbo.ServiceProviderServices_dbo.ServiceProviders_ServiceProviderID\". The conflict occurred in database \"qunadodb\", table \"dbo.ServiceProviders\", column 'ServiceProviderID'.\r\nThe statement has been terminated."}
Maybe it's related to this?
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
Which i used becuase i couldn't create the db otherwise, i had another error.
See below structure:
public class BusinessCategories
{
[Key]
public int CategoryID { get; set; }
public String Title { get; set; }
}
public class BusinessTypes
{
[Key]
public int TypeID { get; set; }
public String Title { get; set; }
public int CategoryID { get; set; }
public virtual BusinessCategories Categories { get; set; }
}
public class ServiceProviders
{
[Key]
public int ServiceProviderID { get; set; }
public String Name { get; set; }
public Int32 TypeID { get; set; }
public virtual BusinessTypes Type { get; set; }
}
public class ServiceProviderServices
{
[Key]
public Int32 ServiceProviderServiceID { get; set; }
public String Price { get; set; }
public Int32 ServiceProviderID { get; set; }
public virtual ServiceProviders ServiceProvider { get; set; }
public Int32 SubServiceID { get; set; }
public virtual SubServices SubService { get; set; }
}
public class ServiceProviderSlots
{
public ServiceProviderSlots()
{
SlotServices = new List<ServiceProviderServices>();
}
[Key]
public Int32 SlotID { get; set; }
public String Name { get; set; }
public Int32 ServiceProviderID { get; set; }
[ForeignKey("ServiceProviderID")]
public virtual ServiceProviders ServiceProvider { get; set; }
public virtual ICollection<ServiceProviderServices> SlotServices { get; set; }
}
this message means that you probably yet have a ServiceProvider with Id = 1 in the database.
in this cas you have to attach the entity to the context.
Related
I had a problem trying to add object from dto.
I have a DTO like this
public class CustomerCourseSessionDto : IDto
{
public int Id { get; set; }
public int? ConnectorId { get; set; }
public List<SomeObject>? SomeObject { get; set; }
public List<OtherObject>? OtherObject { get; set; }
}
and I'm trying to insert this DTO sent from the UI. I'm using a loop(foreach) for this, but it didn't feel right to me.
Maybe entityframework suggests a method for this, idk...
Other objects are like this
public class SomeObject: IEntity
{
public int Id { get; set; }
public int? ConnectorId { get; set; }
}
public class OtherObject: IEntity
{
public int Id { get; set; }
public int? ConnectorId { get; set; }
}
Thanks for the suggestions.
Here is where I use the loop:
[TransactionScopeAspect]
public IResult AddWithDto(CustomerCourseSessionDto courseSessionDto)
{
foreach (var item in courseSessionDto.Participants)
{
_someObjectService.Add(item);
}
foreach (var item in courseSessionDto.Lessons)
{
_otherObjectService.Add(item);
}
_customerCourseSessionDal.Add(new CustomerCourseSession
{
Id = courseSessionDto.Id,
CustomerCourseId = courseSessionDto.CustomerCourseId,
});
return SuccessResult with message ;
}
You should design your entities to have a link to each table using foreign keys.
public class CustomerCourseSession
{
public int Id { get; set; } // Primary Key
public string Name { get; set; }
public virtual ICollection<CourseParticipant> Participants { get; set; }
public virtual ICollection<CourseLesson> Lessons { get; set; }
}
public class CourseParticipant
{
public int Id { get; set; }
public int CustomerCourseSessionId { get; set; } // Foreign Key from CustomerCourseSession
// other fields here
public virtual CustomerCourseSession CustomerCourseSession { get; set;}
}
public class CourseLesson
{
public int Id { get; set; }
public int CustomerCourseSessionId { get; set; } // Foreign Key from CustomerCourseSession
// other fields here
public virtual CustomerCourseSession CustomerCourseSession { get; set;}
}
Then you can just call:
var entity = MapDtoToEntity(courseSessionDto);
_dbContext.CustomerCourseSessions.Add(entity);
_dbContext.SaveChanges();
I have two model class as;
public class MessageDetailModel
{
[Key]
public int messageDetailsId { get; set; }
public MessageModel messageModel { get; set; }
public string detail { get; set; }
public int senderId { get; set; }
public int customerId { get; set; }
public string phone { get; set; }
public DateTime date { get; set; }
}
and
public class MessageModel
{
[Key]
public int messageId { get; set; }
public int senderId { get; set; }
public int customId { get; set; }
public bool ReadInfo { get; set; }
public virtual List<MessageDetailModel> MessageDetails { get; set; }
}
and it is my context class ;
public virtual DbSet<MessageDetailModel> messageDetails { get; set; }
public virtual DbSet<MessageModel> messages { get; set; }
public virtual DbSet<PersonModel> persons { get; set; }
public virtual DbSet<DirectoryModel> directory { get; set; }
I am trying to get messageId over MessageDetailModel but messageId returns as 0 and I have that error "Object reference not set to an instance of an object"
Console.WriteLine(k.messageModel.messageId); //( k is my var which gets from messagedetail model)
How can ı reach messageId over MessadeDetailModel
There is no current link between your two models that would represent a Foreign Key.
You'd need to do something like this for your model if you want a Foreign Key to link to the related object:
public class MessageDetailModel
{
[Key]
public int messageDetailsId { get; set; }
[ForeignKey("messageId")] // Added Data Annotation for the Foreign Key relationship
public MessageModel messageModel { get; set; }
public string detail { get; set; }
public int senderId { get; set; }
public int customerId { get; set; }
public string phone { get; set; }
public DateTime date { get; set; }
public int messageId { get; set; } // This would be your Foreign Key
}
I've added the messageId column to your MessageDetailModel to match the Primary Key column of your MessageModel as that's necessary for the link to form.
You would use the [ForeignKey("messageId")] Data Annotation above the variable for the MessageModel to determine what value it needs to use when finding the object you want.
I'm a newbie to designing database.
I have problem how to define a domain class which has multiple foreign keys linked with a same primary key.
Here is my model:
namespace OceanFmsSystem.Domain
{
public class ExportTemplate
{
public int Id { get; set; }
public List<ExportBooking> ExportBookings { get; set; }
public string TemplateName { get; set; }
public int CustomerId { get; set; }
public string Incoterms { get; set; }
public string IncotermsDetail { get; set; }
public string PaymentTerm{ get; set; }
public int CountryOriginId { get; set; }
public int CountryDestinationId { get; set; }
}
}
What I want to do is that CountryOriginId & CountryDestinationId should refer to the below class as foreign keys:
namespace OceanFmsSystem.Domain
{
public class Country
{
public int Id { get; set; }
public string CountryCode { get; set; }
public string CountryName { get; set; }
}
}
As far as I know, in EF Core there is an convention which I should name a foreign key as below for migration from code to database.
public type ClassNameOfPrimaryKeyId { get; set;}
Is there any possible way to make this happens?
Yes, possible. Your class should look like this:
public class ExportTemplate
{
//...
public int CountryOriginId { get; set; }
public Country CountryOrigin { get; set; }
public int CountryDestinationId { get; set; }
public Country CountryDestination { get; set; }
}
EF is smart enough to figure the Ids by convention. If you do not wish to follow the convention you can use [ForeignKey] attribute on the properties to configure the FK:
[ForeignKey("Origin")]
public int MyOriginId { get; set; }
public Country Origin { get; set; }
I am trying to map properties of the same type on a OneToMany association. I tried to distinguish with Description but kinda stuck here.
public class User
{
public virtual int UserId { get; set; }
public virtual string UserName { get; set; }
[Description("From")]
public virtual IList<Message> FromMessageList { get; set; }
[Description("To")]
public virtual IList<Message> ToMessageList { get; set; }
}
public class Message
{
public virtual int MessageId { get; set; }
public virtual string Text { get; set; }
[Description("From")]
public virtual User FromUser { get; set; }
[Description("To")]
public virtual User ToUser { get; set; }
}
public class DefaultHasManyConvention : IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
if (instance.OtherSide.Property.GetDescription() == instance.Member.GetDescription())
{
if (instance.Member.GetDescription() != null)
instance.Key.Column(instance.Member.GetDescription() + "Id");
else
instance.Key.Column(instance.OtherSide.Property.Name + "Id");
instance.Fetch.Select();
}
}
}
public class DefaultReferenceConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
if (instance.Property.GetDescription() != null)
instance.Column(instance.Property.GetDescription() + "Id");
else
instance.Column(instance.Property.Name + "Id");
instance.Fetch.Select();
}
}
For one to many relationships I generally use coding like :
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
[Description("From")]
public virtual ICollection<Message> FromMessageList { get; set; }
[Description("To")]
public virtual ICollection<Message> ToMessageList { get; set; }
}
public class Message
{
public int MessageId { get; set; }
public string Text { get; set; }
[Description("From")]
public virtual User FromUser { get; set; }
// From user foreign key column
[ForeignKey("FromUser")]
public int FromUserId {get;set;}
[Description("To")]
public virtual User ToUser { get; set; }
// ToUser foreign key column
[ForeignKey("ToUser")]
public int ToUserId {get;set;}
}
Try to use ICollection instead of IList - this solved many issues for me.
Add foreign key column names; it makes mapping simpler and filtering in queries easier.
I'm still new in creating Models using Entity Framework and MVC 4 Razor. I'm having a problem on how can I save a history of a model. How can I create a model that have a history on specific tables or fields ? For ex: If I wish to create a history on the changes on the school. Its still not clear to me how will I I create the model that saves history. How will be the triggering do I have to execute the save function on different models with the same data ?
Thank you so much in advance.
If anyone could be a simple example of model and a model history and how it is functioning, I'll be very grateful. Like a Sales or sales history.
Here's my code
One To Many
public class Child
{
[Key]
public int ChildID { get; set; }
[Required,Display(Name="Project Code")]
public string ProjectCode { get; set; }
public string Status { get; set; }
[DataType(DataType.Date)]
public DateTime StatusDate { get; set; }
public string FamilyName { get; set; }
public string GivenName { get; set; }
public string MiddleName { get; set; }
[DataType(DataType.Date)]
public DateTime Birthdate { get; set; }
public string Gender {get;set;}
public string Address { get; set; }
public string Section { get; set; }
public int SchoolLevelID { get; set; }
public int SchoolYearID { get; set; }
public int AreaID { get; set; }
public int SchoolID { get; set; }
public int GradeLevelID { get; set; }
//Foreign Key - One to Many
public virtual SchoolLevel SchoolLevel { get; set; }
public virtual SchoolYear SchoolYear { get; set; }
public virtual Area Area { get; set; }
public virtual School School { get; set; }
public virtual GradeLevel GradeLevel{get;set;}
//Child is foreign key at the table
public virtual ICollection<Guardian> Guardians { get; set; }
}
public class SchoolLevel
{
public int SchoolLevelID { get; set; }
public string SchoolLevelName { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class SchoolYear
{
public int SchoolYearID { get; set; }
public string SchoolYearName { get; set; }
public virtual ICollection<Child> Children{get;set;}
}
public class Area
{
public int AreaID{get;set;}
public string AreaName { get; set; }
public virtual ICollection<Child> Children{get;set;}
}
public class School
{
public int SchoolID { get; set; }
public string SchoolName{get;set;}
public virtual ICollection<Child> Children { get; set; }
}
public class GradeLevel
{
public int GradeLevelID{get;set;}
public string GradeLevelName { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class ChildDbContext : DbContext
{
public DbSet<Child> Children { get; set; }
public DbSet<SchoolLevel> SchoolLevels { get; set; }
public DbSet<SchoolYear> SchoolYears { get; set; }
public DbSet<Area> Areas { get; set; }
public DbSet<School> Schools { get; set; }
public DbSet<GradeLevel> GradeLevels { get; set; }
public DbSet<Guardian> Guardians { get; set; }
}
You can use this approach: Create a History model. That contains 1 changeness like o log.
public class History
{
public int HistoryId { get; set; }
public int ModelType { get; set; } //it is ModelTypeEnum value.
public int ModelId { get; set; }
public string PropertyName { get; set; }
public string Propertyvalue {get;set;}
public DateTime ChangeDate { get; set; }
public int ChangedUserId { get; set; }
}
And Enum:
public enum ModelTypeEnum
{
Child =1,
SchoolLevel = 2,
//etc..
};
For example, when you edit 1 Child entity, give changed properties name and value, it's id, type and others (ChangeDate, ChangedUserId) to History and save histories. If 3 properties will change you should save 3 history entities. Then, you can load (filter) histories by ModelId, by ChangedUserId etc.