I need build a link between two libraries in .NET Core using the code-first approach.
I need to build a link between the countries table from the standards library and the table with trade forms.
Both libraries operate on separate contexts.
Relationships between projects can be added unidirectionally because if you try to add a bidirectional constraint, you get a circular error.
Is there any way to build such a relationship?
public class CountryStandard
{
[Key]
public int IdCountryStandard { get; set; }
[Required(ErrorMessage = "Select Country")]
[Display(Name = "Name Country")]
[MaxLength(80, ErrorMessage = "Name max 80")]
public string NameCountryStandard { get; set; }
public bool IsActive { get; set; }
[JsonIgnore]
//public virtual Standard Standard { get; set; }
public virtual ICollection<Standard> Standard { get; set; }
public virtual ICollection<TradeForms> TradeForms { get; set; }
}
public class TradeForms
{
[Key]
public int TradeFormsId { get; set; }
/...
.../
public int IdCountryStandard { get; set; }
public CountryStandard CountryStandard { get; set; }
}
After building the relationship, I would add to the Fluent API
And he did the database migration.
But I don't know if it is possible to build relationships between separate libraries from code-first in this way.
No, it isn't possible to do circular referencing in .NET.
Solution 1 I recommend
Merge Standard.DAL and Trade.DAL in one project DAL.
Solution 2
Remove in Standard.DAL all reference to Trade.DAL. For example with CountryStandard :
public class CountryStandard
{
[Key]
public int IdCountryStandard { get; set; }
...
public virtual ICollection<Standard> Standard { get; set; }
// Remove - public virtual ICollection<TradeForms> TradeForms { get; set; }
}
Solution 3
If you really need this navigation property, you can apply the solution 2 and extend standard entities to add removed navigation properties. For example with Standard.DAL.CountryStandard, you can extend in the Trade.DAL project to :
namespace Trade.DAL
{
public class TradeCountry : CountryStandard
{
public ICollection<TradeForms> TradeForms { get; set; }
}
}
Then in the context :
namespace Trade.DAL
{
public class TradeEntities : DbContext
{
...
public DbSet<TradeForms> TradeForms { get; set; }
public DbSet<TradeCountry> TradeCountries { get; set; }
}
}
I'm trying to think of a way to store actual templates of ticket items in my Entity Framework MVC project. The thing is, I've already done a Code First migration process in the past. What I need to do is create logic in my code to allow someone to save time creating a ticket by using pre-loaded data from a template. My current inheritance model uses an abstract class (MasterTicket) which is used as the parent since to me there can be multiple categories (a Google Calendar based task, "Appointment Task" and a purely internal task, "General Task"). Here's my parent abstract class:
[Table("Ticket")]
[ModelBinder(typeof(MasterTicketBinder))]
public abstract class MasterTicket
{
[Key]
public Guid id{ get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ART { get; set; }
public DateTime openTime{ get; set; }
public DateTime? closeTime { get; set; }
private bool active = true;
public bool Active{ get => active; set => active = value; }
public string summary{ get; set; }
public string description{ get; set; }
public DateTime updateTime{ get; set; }
//TODO: Create foreign key relationship to user model
public Guid userUpdateId{ get; set; }
//TODO: Create foreign key relationship for tickets from other systems
public Guid externalAppId{ get; set; }
//TODO: Create foreign key relationship to user model
public Guid userOpenId{ get; set; }
public Guid? userCloseId { get; set; }
public Guid userOwnerId{ get; set; }
private int timesUpdated = 0;
public int TimesUpdated { get => timesUpdated; set => timesUpdated = value; }
public DateTime expectedCompletionTime{ get; set; }
public DateTime actualCompletionTime{ get; set; }
public List<MasterTicketItem> masterTicketItems{ get; set; }
public MasterTicket()
{
}
}
An here's an example of the concrete Google Calendar-based "Appointment Task" child:
[Table("AppointmentTickets")]
public class ApptTaskTicket : MasterTicket
{
public DateTime currentApptTime { get; set; }
public DateTime? endApptTime { get; set; }
public bool allDay { get; set; }
public string customerName { get; set; }
//TODO: Create foreign relationship
public Guid subjectPrsnlId { get; set; }
public string gCalEventId { get; set; }
public string customerPhone { get; set; }
public string customerEmail { get; set; }
public string preferredContactMethod { get; set; }
public List<ApptConfirmItem> apptConfirmItems { get; set; }
}
I know I can easily create a column for the MasterTicket class to indicate that it's a template, but to me I feel it's cleaner to have a separate "Template Table" if you will that will store pre-existing values that can be filled in with a form. In this case, I think I would WANT to create a duplicate class that would store said templates so that there are only several rows. What would be the best way to do this with Code First? Does someone feel I should take a different approach? Maybe DB First is a better way to go?
In case it matters, here's my DBContext for the Tickets:
// Code-Based Configuration and Dependency resolution
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class TicketDB : DbContext
{
public TicketDB(): base("AffirmativeServiceSystem.Properties.Settings.AffirmTaskManager")
{
}
public DbSet<MasterTicket> tickets { get; set; }
public DbSet<MasterTicketItem> ticketItems { get; set; }
}
This is my first time here so sorry if I did not put the doubt by default. In my project I have two models class doubts and a class of works, I want to create a classification for both using a superclass, like the design pattern strategy. But I have a problem, the project state is advanced and I have used the doubt and works classes many times. Already tried in many ways, but either the error in the update-database or the error in what I had done before.
Does anyone know one way that I can implement a generic class classification for the doubts and works classes without many changes of what I had already done?
My code is below
public abstract class Classificable
{
[Key]
public int id { get; set; }
public virtual Classification classication { get; set; }
}
public class Doubt : Classificable
{
public int doubtID { get; set; }
public string question { get; set; }
public string content { get; set; }
public virtual Student student { get; set; }
public virtual Course course { get; set; }
public virtual Work work { get; set; }
public virtual ICollection<Answer> answers { get; set; }
}
public class Work : Classificable
{
public int workID { get; set; }
public string name { get; set; }
public string nameWork { get; set; }
public string filePath { get; set; }
public virtual Student student { get; set; }
public virtual Course course { get; set; }
public virtual ICollection<Doubt> doubts { get; set; }
}
public class DB_DIS : DbContext
{
public DB_DIS()
: base("name=DB_DIS")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Doubt>().ToTable("Doubts");
modelBuilder.Entity<Work>().ToTable("Works");
}
public virtual DbSet<Doubt> Doubts { get; set; }
public virtual DbSet<Work> Works { get; set; }
}`
What is the property or method in Classificable that you are trying to apply to Doubt and Work?
Have you written your data structure in such a way that is contains an id field AND workID feild?
In my experience, if you are trying to share properties between EF Classes you are better off sharing common fields. I've used it in the past for base classes of AuditableBase as follows:
public class AuditableBase
{
public string UpdateUserId { get; set; }
public DateTime UpdateDate { get; set; }
}
Then all my classes that I want to "Audit" will have a UpdateUserId and UpdateDate, and I can do some pre-save processing to set those based on the type of AuditableBase.
I am trying to create base entity class for Update and Delete for all classes.
I created class and interfaces below (Do not know correct or not)
Entity Class (This is my base entity class)
public class Entity
{
public int Id { get; set; }
public int? CreatorId { get; set; }
public DateTime? CreatedDate { get; set; }
public bool IsDeleted { get; set; }
public List<Delete> DeletedUser { get; set; }
public List<Update> UpdatedUser { get; set; }
}
Delete Interface
public interface Delete
{
int? DeletedId { get; set; }
DateTime? DeletedTime { get; set; }
}
Update Interface
public class Update
{
public int? UpdatedId { get; set; }
public DateTime? UpdatedTime { get; set; }
}
If i set object below and use UpdatedUser and DeletedUser can not reach DeletedId,DeletedTime or UpdatedId,UpdatedTime
ActionResult
BaseEntity.Entity baseEntity = new BaseEntity.Entity();
baseEntity.UpdatedUser. (UpdatedId) can not reach here
Updated user and Deleted User can be multiple however i can not reach from baseEntity.UpdatedUser. or baseEntity.DeletedUser.
How can i create baseentity class in order to use OOP in .net?
They are not single objects, they are lists. When you have a list and you try to access a property of single object on that list, it doesn't make any sense. If you wanna access properties of a user, then get the user you want first then you can access it's properties.
I am desperate to find out how to architect my Entity Framework 4 (code first) application.
I have one VS project that will handle access to my data. Its a MEF-Exported Part [MyData], based on an Interface [IDataExport]. That project has my EF classes (customer, order, etc), the context initializer, etc and all that already works like a dream.
I have one VS project that has my interfaces (all my interfaces). All projects have a reference to this Interface project.
I have one VS project that does all my logging. It is also a MEF-Exported Part [MyLog], based on an interface [ILogging]. That class really just writes to the Console.
I have Three VS projects that we will call Parts (in MEF terms). They are plugins. They need data to work (customers, orders, etc). Actually, they need data as an Input from three different tables, all at once.
I have one project that is the Host application. It is currently running as a console application but will soon be converted to a Windows Service.
I hope that gave you a good idea of the architecture that is in place. Now I am having troubles trying to figure out how to do my data access correctly.
When the host needs data to pass to the plugins, it needs to get data from 3 different tables. Actually, the way it is setup with EF, the three tables will be retrieved at once. How do I pass that data to the plug-in, when the plugin was instantiated by MEF? Can Plug-Ins raise events to interact with the Host application?
In addition, as the plug-ins run, data in the tables will need to be updated. How do I keep my data in the database updated three layers up? The Host can call the Plug-In, but the Plugin doesn't have a way to call the Host. Only the [MyData] project has access to the Database.
Based on the scenario that I described, could someone please tell me how to best architect this application?
Adding further to my confusion, some sample code shows the calling application (in this case the host), starting brand new Models for each search call to the database. e.g.
public List<Customer> FindCustomerList(string companyName)
{
return new CustomerManager().FindCustomerList(companyName);
}
public List<Customer> FindCustomerList(string companyName)
{
var q = from c in context.Customers
where c.CompanyName.StartsWith(companyName)
select c;
return q.ToList();
}
Below are my three tables. Please note that they have foreign key relationships, resulting in sub-items being embedded inside of the main job record. Like a customer with many orders.
public class pcJobAction : IVersionTracking, IpcIdentity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
//IpcIdentity
[Required]
[MaxLength(75)]
public string name { get; set; }
[MaxLength(1000)]
public string description { get; set; }
[Required]
[MaxLength(30)]
public string ServerName { get; set; }
[MaxLength(20)]
public string ServerIP { get; set; }
public int JobEnabled { get; set; }
public virtual ICollection<pcPlugInValue> PlugInText { get; set; }
//JobActions holds a list of Schedules
public virtual ICollection<pcJobSchedule> JobSchedules { get; set; }
//FK to the JobTypes table (Delete Files, Verify Backups, Ping, etc)
public long pcJobTypeId { get; set; }
public virtual pcJobType pcJobType { get; set; }
//IVersionTracking
public DateTime DateCreated { get; set; }
public DateTime LastUpdated { get; set; }
[Timestamp]
public byte[] Version { get; set; }
}
public class pcPlugInValue : IVersionTracking, IpcIdentity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
//IpcIdentity
[Required]
[MaxLength(75)]
public string name { get; set; }
[MaxLength(1000)]
public string description { get; set; }
public string PlugInText { get; set; }
public int ExecuteOrder { get; set; }
//FK to the JobAction table
public long pcJobActionId { get; set; }
public virtual pcJobAction pcJobAction { get; set; }
//FK to the codes table (to indetify the schedule type: daily, weekly, etc)
public long pcCodeId { get; set; }
public virtual pcCode pcCode { get; set; }
//IVersionTracking
public DateTime DateCreated { get; set; }
public DateTime LastUpdated { get; set; }
[Timestamp]
public byte[] Version { get; set; }
}
public class pcJobSchedule : IVersionTracking, IpcIdentity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
//IpcIdentity
[Required]
[MaxLength(75)]
public string name { get; set; }
[MaxLength(1000)]
public string description { get; set; }
//FK to the JobAction table
public long pcJobActionId { get; set; }
public virtual pcJobAction pcJobAction { get; set; }
//FK to the codes table (to indetify the schedule type: daily, weekly, etc)
public long pcCodeId { get; set; }
public virtual pcCode pcCode { get; set; }
public DateTime StartDate { get; set; }
public Boolean dayMonday { get; set; }
public Boolean dayTuesday { get; set; }
public Boolean dayWednesday { get; set; }
public Boolean dayThursday { get; set; }
public Boolean dayFriday { get; set; }
public Boolean daySaturday { get; set; }
public Boolean daySunday { get; set; }
public Boolean ThisJobIsNext { get; set; }
public DateTime EndDate { get; set; }
public int DateOfMonth { get; set; }
public int DayOfWeek { get; set; }
public DateTime ScheduleHour { get; set; }
public int EveryHowMany { get; set; }
public DateTime RunTimeLast { get; set; }
public DateTime RunTimeNext { get; set; }
//IVersionTracking
public DateTime DateCreated { get; set; }
public DateTime LastUpdated { get; set; }
[Timestamp]
public byte[] Version { get; set; }
}
From your architecture description, can I assume that your host application has, somewhere, an [ImportMany] that causes all of your plugins to be instantiated by MEF?
If that is the case, one option is (as I believe you asked) to add an event to your plugin interfaces and attach to that event in each plugin from your host application. I have done that myself and it works fine.
Another option, if it fits into your architecture, is to put your EF classes in a separate assembly, reference that assembly in your plugin assemblies, and do your data access directly from the plugins.
I've done the second option myself, where I have placed my EF code-firstclasses into a seperate assembly, and have some helper classes that are used to connect to the contextclass, and query the ef repository.
However, if you don't want your plugins to have direct access to the entire database, then its probably best to do option 1. Especially if in the future you decided to have your database tables split into different schemas, and you want only certain plugins to be only to interact with specific schema within your database.