I have the following two classes:
public class Record
{
public int RecordId { get; set; }
public DateTime? InsertDate { get; set; } = DateTime.Now;
public DateTime BookingDate { get; set; }
public string AmountTypeName { get; set; }
public double? Amount { get; set; }
public string BookingAccountID { get; set; }
public string AccountCurrency { get; set; }
public string ClientCurrency { get; set; }
public string AffectsBalance { get; set; }
public double? AmountAccountCurrency { get; set; }
public string AmountClientCurrency { get; set; }
public int UnifiedInstrumentCode { get; set; }
public InstrumentInfo InstrumentInfo { get; set; }
}
public class InstrumentInfo
{
[Key]
public int UnifiedInstrumentCode { get; set; }
public ICollection<Record> Record { get; set; }
public string AssetType { get; set; }
public int UnderlyingInstrumentUic { get; set; }
public string UnderlyingInstrumentSubType { get; set; }
public string InstrumentSymbol { get; set; }
public string InstrumentDescription { get; set; }
public string InstrumentSubType { get; set; }
public string UnderlyingInstrumentAssetType { get; set; }
public string UnderlyingInstrumentDescription { get; set; }
public string UnderlyingInstrumentSymbol { get; set; }
}
that I want to use as my context for EF6.
I defined the context the following way:
public class TransactionsContext: DbContext
{
public DbSet<Record> Records { get; set; }
public DbSet<InstrumentInfo> InstrumentInfos { get; set; }
public TransactionsContext()
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<TransactionsContext>(null);
base.OnModelCreating(modelBuilder);
}
}
If I run a test against it that shall add and InstrumentInfo object to the DB
[TestMethod]
public void AddInstrumentInfo_Added_IsTrue()
{
InstrumentInfo info = FakeFactory.GetInstrumentInfo();
using (var ctx = new TransactionsContext())
{
ctx.InstrumentInfos.Add(info);
ctx.SaveChanges();
}
}
I get the following exception:
SqlException: Cannot insert the value NULL into column
'UnifiedInstrumentCode', table
'TransactionsContext.dbo.InstrumentInfoes'; column does not allow
nulls. INSERT fails. The statement has been terminated.
I tried all different scenarios that I found here but I couldn't figure out what I'm doing wrong.
The ultimate goal is that i define my two classes in a way so that a "Record" is linked to the "InstrumentInfo" table via the "UnifiedInstrumentCode" property.
My guess is that my constraints for this two tables are still not correct, but I cant figure out how to define it in EF6 (code first) to get this working.
Adding the annotation [DatabaseGenerated(DatabaseGeneratedOption.None)] to my primary key in InstrumentInfo solved the problem:
public class InstrumentInfo
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UnifiedInstrumentCode { get; set; }
public ICollection<Record> Record { get; set; }
public string AssetType { get; set; }
public int UnderlyingInstrumentUic { get; set; }
public string UnderlyingInstrumentSubType { get; set; }
public string InstrumentSymbol { get; set; }
public string InstrumentDescription { get; set; }
public string InstrumentSubType { get; set; }
public string UnderlyingInstrumentAssetType { get; set; }
public string UnderlyingInstrumentDescription { get; set; }
public string UnderlyingInstrumentSymbol { get; set; }
}
I did not investigate further but my guess is that if a new Record is added, EF initially creates and InstrumentInfo object that has a Null Value for its Primary key which causes the Exception.
I hope it helps if somebody runs into the same problem in future.
Related
I have a task which requires me to return all models from a table using inheritance (TPH).
I have a model class called WorkflowInstance and a derived class CustomWorkflowInstance (which has a string property). There is a discriminator of course.
I want to know of a way where I can return all the elements without considering the discriminator
public class WorkflowInstance : Entity, ITenantScope, ICorrelationScope
{
public WorkflowInstance();
public SimpleStack<ActivityScope> Scopes { get; set; }
public SimpleStack<ScheduledActivity> ScheduledActivities { get; set; }
public WorkflowFault? Fault { get; set; }
public HashSet<BlockingActivity> BlockingActivities { get; set; }
public IDictionary<string, IDictionary<string, object?>> ActivityData { get; set; }
public WorkflowOutputReference? Output { get; set; }
public WorkflowInputReference? Input { get; set; }
public Variables Variables { get; set; }
public Instant? FaultedAt { get; set; }
public Instant? CancelledAt { get; set; }
public Instant? FinishedAt { get; set; }
public Instant? LastExecutedAt { get; set; }
public Instant CreatedAt { get; set; }
public string? Name { get; set; }
public string? ContextId { get; set; }
public string? ContextType { get; set; }
public string CorrelationId { get; set; }
public WorkflowStatus WorkflowStatus { get; set; }
public int Version { get; set; }
public string? TenantId { get; set; }
public string DefinitionId { get; set; }
public ScheduledActivity? CurrentActivity { get; set; }
public string? LastExecutedActivityId { get; set; }
}
public class CustomWorkflowInstance : WorkflowInstance
{
public Guid UserId { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<WorkflowInstance>()
.HasDiscriminator<int>("Discriminator")
.HasValue(0)
.HasValue<WorkflowInstance>(0)
.HasValue<CustomWorkflowInstance>(1);}
I want to find a way to query the table as it is meaning adding where clause FinishedAt > etc (the issue is that UserId exist only in derived class but all the data is in base class where discriminator always equals 0)
so by doing select * from WorkflowInstanceTABLE where Used="xx" it automatically adds the where discriminator = 1 (because I wrote _dbContext.CustomWorkflowInstance which contains the userId in question.
I have a view in my SQL database. All I want is to retrieve data from that view.
I have added POCO class.
namespace WFPersistence.DataModel
{
public class Instance
{
public Guid InstanceId { get; set; }
public DateTime? PendingTimer { get; set; }
public DateTime? CreationTime { get; set; }
public DateTime? LastUpdatedTime { get; set; }
public int? ServiceDeploymentId { get; set; }
public string SuspensionExceptionName { get; set; }
public string SuspensionReason { get; set; }
public string ActiveBookmarks { get; set; }
public string CurrentMachine { get; set; }
public string LastMachine { get; set; }
public string ExecutionStatus { get; set; }
public bool? IsInitialized { get; set; }
public bool? IsSuspended { get; set; }
public bool? IsCompleted { get; set; }
public byte? EncodingOption { get; set; }
public byte[] ReadWritePrimitiveDataProperties { get; set; }
public byte[] WriteOnlyPrimitiveDataProperties { get; set; }
public byte[] ReadWriteComplexDataProperties { get; set; }
public byte[] WriteOnlyComplexDataProperties { get; set; }
public string IdentityName { get; set; }
public string IdentityPackage { get; set; }
public long? Build { get; set; }
public long? Major { get; set; }
public long? Minor { get; set; }
public long? Revision { get; set; }
}
public class Instances : Collection<Instance>
{
}
}
This is how I am trying to map with view.
public class WFPersistenceStore : DbContext
{
public WFPersistenceStore() : base("WFPersist")
{
}
public DbSet<Instance> PersistedInstances { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Instance>().ToTable("System.Activities.DurableInstancing.Instances");
}
}
This is how I am connecting with view
using (var PersistStore = new WFPersistenceStore())
{
var result = from t in PersistStore.PersistedInstances
select t;
////
///
}
I am getting this error:
An unhandled exception of type 'System.ArgumentException' occurred in
RentalHost.exe
Additional information: The database name
'System.Activities.DurableInstancing.Instances' is invalid. Database
names must be of the form [.].
Your method should be like
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Instance>().ToTable("Instances");
}
I have resolved my issue by just putting the following line inside the constructor of my context class (i.e. WFPersistenceStore).
Database.SetInitializer<WFPersistenceStore>(null);
This wasn't mentioned anywhere clearly in official documents if i am not wrong.
The above line needed for EF6 version only but not required for earlier versions of EF.
I am a VB.NET programmer, but I am trying to learn C# and MVC in my spare time. I am using ASP.NET MVC 5.1.0.0 and I am trying to do code-First database creation in a local instance of SQL Server.
I was able to get the first database table to update in the database when I ran Update-Database from within the IDE, but when I added a second table that has a PK/FK relationship with the first, I am getting a red line under [ForeignKey] which reads
Does not contain a constructor that takes 1 arguments
I have been searching all over and not getting anywhere. Any suggestions or help would be appreciated. By the way, the first table is a PK/FK relationship to the AspNetUsers table.
public class BuildDatabase : IdentityUser
{
public virtual Companies Companies { get; set; }
public virtual NotaryProfile NotaryProfile { get; set; }
}
public class Companies
{
[Key]
[Column("CompanyID")] // Did this as the database will reflect TableName_ColumnName instead.
public int CompanyID { get; set; }
public string CompanyName { get; set; }
public bool IsActive { get; set; }
public bool IsNotary { get; set; }
public virtual ICollection<NotaryProfile> NotaryProfile { get; set; }
}
public class NotaryProfile
{
[Key]
public int NotaryID { get; set; }
public string NamePrefix { get; set; }
public string FirstName { get; set; }
public string MiddleInitial { get; set; }
public string LastName { get; set; }
public string NameSuffix { get; set; }
public bool IsActive { get; set; }
public int DefaultState { get; set; }
public int DefaultCounty { get; set; }
public bool IsSigningAgent { get; set; }
public bool HasABond { get; set; }
public decimal BondAmount { get; set; }
public bool HasEandO { get; set; }
public decimal EandOAmount { get; set; }
public bool ElectronicNotarizationsAllowed { get; set; }
public string ElectronicTechnologyUsed { get; set; }
public string ComissionNumber { get; set; }
public DateTime CommissionIssued { get; set; }
public DateTime CommssionOriginal { get; set; }
public DateTime CommissionExpires { get; set; }
public DateTime CommissionFiledOn { get; set; }
public string SOSAuditNumber { get; set; }
public string CommissionDesc { get; set; }
[Foreignkey("CompanyID")] // Companies.CompanyID = PK
public int CompanyID { get; set; } // PK/FK relationship.
public Companies Companies { get; set; } // Reference to Companies table above.
}
public class SchemaDBContext : IdentityDbContext<BuildDatabase>
{
public SchemaDBContext()
: base("DefaultConnection"){}
public DbSet<Companies> Companies { get; set; }
public DbSet<NotaryProfile> NotaryProfile { get; set; }
}
One of your classes (probably NotaryProfile) needs to reference another object (the foreign key relationship) but there is no constructor in that class that accepts an argument to establish that relationship, e.g.:
public NotaryProfile(int companyId) {
this.companyId = companyId;
}
BTW, a better way to establish that relationship is to use the actual class type rather than the ID, as in:
public class NotaryProfile {
...
public Company Company { get; set; }
// Instead of this:
// public int CompanyID { get; set; } // PK/FK relationship.
...
}
See also:
C# “does not contain a constructor that takes '1' arguments”
Does not contain a constructor that takes 2 arguments
I have the following 2 models:
public class Alert
{
public int Id { get; set; }
public DateTime AlertDatetime { get; set; }
public bool Unread { get; set; }
public int? ReadByUserId { get; set; }
public DateTime? ReadDateTime { get; set; }
public DateTime ImportDateTime { get; set; }
public bool AlertHasRecords { get; set; }
//Error Reporting and Recording.
public bool Error { get; set; }
public string ErrorText { get; set; }
public virtual IEnumerable<AlertRecord> Records { get; set; }
}
public class AlertRecord
{
public int Id { get; set; }
public string HospitalNumber { get; set; }
public string ForeName { get; set; }
public string SurName { get; set; }
public DateTime DateOfBirth { get; set; }
public DateTime EventDateTime { get; set; }
public string CrisNumber { get; set; }
public DateTime CreationDateTime { get; set; }
//Link it back to the master Alert!
public int AlertId { get; set; }
public virtual Alert Alert { get; set; }
}
Once the "Alert" Object properties have values in them, I am trying to use EntityFramework to inset this object into my SQL DB like this:
class Program
{
private static Alert MainAlert = new Alert();
private static PrimaryDBContext db = new PrimaryDBContext();
static void Main(string[] args)
{
MainAlert = AlertObjectFactory.GetAlertObject();
db.Alerts.Add(MainAlert);
db.SaveChanges();
}
}
The AlertObjectFactory.cs and The Class responsible for building the list of AlertRecords are here(They are large class files)
https://gist.github.com/anonymous/67a2ae0192257ac51f39
The "Alert" Table is being populated with data, however the 4 records in the
IEnumerable Records
are not being inserted...
Is this functionality possible with EF?
Try changing your IEnumerable to something that implements ICollection such as List
See this answer for more details
I have a database with 3 tables:
Subjects
Members
Topics
Then I added the connection string to web.config and created an EF with the following classes:
namespace MySite.Models
{
public class MySiteDBModel : DbContext
{
public DbSet<Topic> Topics { get; set; }
public DbSet<Subject> Subjects { get; set; }
public DbSet<Member> Members { get; set; }
public DbSet<TopicDataModel> TopicDataModel { get; set; }
protected override void OnModelCreating(DbModelBuilder mb)
{
mb.Conventions.Remove<PluralizingTableNameConvention>();
}
}
public class Topic
{
[Key]
public int TopicID { get; set; }
public int SubID { get; set; }
public int MemberID { get; set; }
public string TDate { get; set; }
public string Title { get; set; }
public string FileName { get; set; }
public int Displays { get; set; }
public string Description { get; set; }
public virtual Subject Subject { get; set; }
public virtual Member Member { get; set; }
public virtual ICollection<TopicView> TopicView { get; set; }
}
public class Subject
{
[Key]
public int SubID { get; set; }
public string SubName { get; set; }
public virtual ICollection<Topic> Topic { get; set; }
}
public class Member
{
[Key]
public int MemberID { get; set; }
public string FLName { get; set; }
public string Email { get; set; }
public string Pwd { get; set; }
public string About { get; set; }
public string Photo { get; set; }
public virtual ICollection<Topic> Topic { get; set; }
}
public class TopicDataModel
{
[Key]
public int TopicID { get; set; }
public string SubName { get; set; }
public string FLName { get; set; }
public string TDate { get; set; }
public string Title { get; set; }
public int Displays { get; set; }
public string Description { get; set; }
}
}
Now when I am trying to query the database with the this code:
public ActionResult Index()
{
var topics = from t in db.Topics
join s in db.Subjects on t.SubID equals s.SubID
join m in db.Members on t.MemberID equals m.MemberID
select new TopicDataModel()
{
TopicID = t.TopicID,
SubName = s.SubName,
FLName = m.FLName,
TDate = t.TDate,
Title = t.Title,
Displays = t.Displays,
Description = t.Description
};
return View(topics.ToList());
}
I got this Error:
The model backing the 'MySiteDBModel' context has changed since the
database was created. Either manually delete/update the database, or
call Database.SetInitializer with an IDatabaseInitializer instance.
For example, the DropCreateDatabaseIfModelChanges strategy will
automatically delete and recreate the database, and optionally seed it
with new data.
Please help me!!!!!!
You need to set some controls on how EF is handling changes to your data model. Julie Lerman has a good blog post on Turning Off Code First Database Initialization Completely.
Also, here is a good overview - Inside Code First Database Initialization