Using foreign Key in DbInitialize class. Code First - asp.net-mvc-3

I have two entities
public class Datatype
{
[Key]
public int Id { get; set; }
[StringLength(96)]
public string DataTypeName { get; set; }
}
public class Attribute
{
[Key]
public int Id { get; set; }
[StringLength(96)]
public string Attribute_Name { get; set; }
[ForeignKey("Datatype")]
public int? DatatypeId { get; set; }
public virtual Datatype Datatype { get; set; }
}
In DataBase Initialize I have this code
Datatype dt = new Datatype();
dt.DataTypeName = "text";
context.datatypes.Add(dt);
//Above code is working fine. And After execution I can see
//in records a row.. with id=1 and datatype=text
Attribute at = new Attribute();
at.Attribute_Name = "Description";
//at.DatatypeId = 1; But if I uncomment this line
context.attributes.Add(at); // Then This Gives Following Error
The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_dbo.Attributes_dbo.Datatypes_DatatypeId". The conflict occurred in database
"dyescan", table "dbo.Datatypes", column 'Id'

Assuming that the above code executes before either of the two objects have been saved to the database then it will not work simply because your object 'dt' will not have an ID of 1 before it's been saved to the database and therefore you cannot associate with attribute on '1' YET!
Instead you should not set the 'DatatypeId' but simply set the 'Datatype' like so:
at.Datatype = dt;
This will leave entity framework to figure out what the actual foreign key associated should/would be when savechanges is called.

Related

Using Intersection between two lists inside where statement of Linq

I have a parent table named Employees which has a foreign key in a child table EmployeePrisons as follows
public class EmployeePrisons : FullAuditedEntity<long>
{
public long EmployeeId { get; set; }
public long PrisonId { get; set; }
public Employee Employee { get; set; }
public PrisonsLkpt Prison { get; set; }
}
Now i want the user to be able to select more than one prisons, to find all the employees that work in that list of prisonsIds. So i was thinking of using intersect inside the where clause. like this
The variable prisons is also list
employees=employees.Where(x => x.Prisons.Select(c => c.PrisonId).ToList().Intersect(prisons).Count()!=0 && x.Attendance.Any(y => y.ExitTime == null));
But it always give this error:
Expression of type 'System.Collections.Generic.List1[System.Int64]' cannot be used for parameter of type 'System.Linq.IQueryable1[System.Int64]' of method
'System.Linq.IQueryable1[System.Int64] Intersect[Int64](System.Linq.IQueryable1[System.Int64],
System.Collections.Generic.IEnumerable`1[System.Int64])' (Parameter
'arg0')
Please if anyone can help me it will be very useful

SQlite Update Statement in xamarin forms

I have an SQlite table with 4 Columns in Xamarin app.
I've already inserted 3 columns and now i need an update statement to Update 4th column with some values using for loop.
(OR)
Please suggest any better/other method to do the same.
Do you want to update the record in the sqlite DB?
If so you can use this model to update the record in the DB.prijem.BCode is PrimaryKey, we set the type of PrimaryKey is int and AutoIncrement, So, if the model's PrimaryKey is not equal zero, this record stored in the DB, we can update this record by the Model.
readonly SQLiteAsyncConnection _database;
public PrijemDatabase(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<Prijem>().Wait();
}
public Task<int> SavePrijemAsync(Prijem prijem)
{
if (prijem.BCode != 0)
{
return _database.UpdateAsync(prijem);
}
else
{
return _database.InsertAsync(prijem);
}
}
Here is my model.
public class Prijem
{
[PrimaryKey, AutoIncrement, Unique]
public int BCode { get; set; }
public string Name { get; set; }
public string FirmName { get; set; }
public string ItemCode { get; set; }
public string Count { get; set; }
}
Here is link about how to execute CRUD, you can refer to it.
https://learn.microsoft.com/en-us/xamarin/get-started/quickstarts/database?pivots=windows
Here is a demo about it.
https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/getstarted-notes-database/

Entity framework is making the id null on insert

I'm getting the following error when I try to insert a new row in one of my relational tables. I have the following two models:
public class CompanyCredit
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int creditId { get; set; }
public int planCredit { get; set; }
public DateTime? PlanCreditExpirationDate { get; set; }
}
And
public class CompanyInformation
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[Required]
[DisplayName("Company Name:")]
public string companyName { get; set; }
public string timeZone { get; set; }
//navigation Properties
public virtual CompanyCredit Credits { get; set; }
}
And this Relation in the dbContext
modelBuilder.Entity<CompanyInformation>().HasOptional(e => e.Credits);
I'm trying to add a record inside CompanyCredit table like so:
if (_company.Credits == null)
{
var _credits = new CompanyCredit();
_credits.planCredit = 200;
_credits.PlanCreditExpirationDate = System.DateTime.UtcNow.AddMonths(1);
_company.Credits = _credits;
repo.InsertOrUpdate(_company, User.Identity.Name);
}
And Finally Insert or update just marks Company as changed and _credit as added like so:
_db.Entry(_credits).State = System.Data.EntityState.Added;
_db.Entry(Company).State = System.Data.EntityState.Modified;
_db.SaveChanges();
When this runs I get the following Error that I just can't seem to find the reason to.
Cannot insert the value NULL into column 'creditId', table 'Project.dbo.CompanyCredits'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Thank in advanced for your help.
I found the problem was in the attribute [DatabaseGenerated(DatabaseGeneratedOption.Identity)] this should have been [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
I thought I would post this so others might benefit from it.
Could you please try reversing the order of entity state modification, just before the saveChanges call
_db.Entry(Company).State = System.Data.EntityState.Modified;
_db.Entry(_credits).State = System.Data.EntityState.Added;
_db.SaveChanges();

Insert null fails with Model First EF

I'm using a context generated from an EDMX for a mvc3 webapp. I'm getting a NULL insert fails error on an entity
[Serializable]
[DataContract(IsReference = true)]
[EdmEntityType(NamespaceName = "Model", Name = "Thing")]
public class Thing: EntityObject
{
public RolloverEntry();
[DataMember]
[EdmScalarProperty(EntityKeyProperty = true, IsNullable = false)]
public int id { get; set; }
[SoapIgnore]
[EdmRelationshipNavigationProperty("Model", "FK_ThingStep1", "Step1")]
[DataMember]
[XmlIgnore]
public EntityCollection<Step1> Step1 { get; set; }
[SoapIgnore]
[EdmRelationshipNavigationProperty("Model", "FK_ThingStep2", "Step2")]
[XmlIgnore]
[DataMember]
public EntityCollection<Step2> Step2 { get; set; }
public static Thing CreateThing(int id);
}
Data access to other parent-child relationships are working and persisted correctly - I can't seem to find what's wrong with this table tho - any ideas appreciated
Exception Recieved:
{"Cannot insert the value NULL into column 'id', table 'myapp.dbo.Thing'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
Thanks
I'm guessing you need some sort of hint in your model that the database should generate the ids for the id column. You might want to see if StoreGeneratedPattern is set to Identity for your model property id or something along those lines.

Entity Framework, MVC 3, One-to-many relationship

Ok - first off apologies - I'm a front end developer (HTML, CSS and JS) trying to do stuff with data - never pretty!
I have a 'Page', that can can have one or many 'Series'. These 'Series' can hold one or many 'Collections' and these 'Collections' can be related to more than one 'Series'. The 'Collection's can hold one or more 'Titles'. This is how I've structured my db:
CREATE TABLE [dbo].[Pages] (
PageId INT NOT NULL PRIMARY KEY,
[Title] NCHAR(50) NOT NULL
)
CREATE TABLE [dbo].[Series] (
[SeriesId] INT NOT NULL,
[Title] NCHAR (50) NOT NULL,
[PageId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([SeriesId] ASC),
CONSTRAINT [FK_Series_Pages] FOREIGN KEY ([PageId]) REFERENCES [Pages]([PageId])
);
CREATE TABLE [dbo].[Collections] (
[CollectionId] INT NOT NULL,
[Title] NCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([CollectionId] ASC)
);
CREATE TABLE [dbo].[SeriesCollections] (
[SeriesCollectionId] INT NOT NULL,
[SeriesId] INT NOT NULL,
[CollectionId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([SeriesCollectionId] ASC),
CONSTRAINT [FK_SeriesCollections_Series] FOREIGN KEY ([SeriesId]) REFERENCES [Series]([SeriesId]),
CONSTRAINT [FK_SeriesCollections_Collections] FOREIGN KEY ([CollectionId]) REFERENCES [Collections]([CollectionId])
);
CREATE TABLE [dbo].[Titles] (
[TitleId] INT NOT NULL,
[Title] NCHAR (100) NOT NULL,
[SeriesCollectionId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([TitleId] ASC),
CONSTRAINT [FK_Titles_SeriesCollections] FOREIGN KEY ([SeriesCollectionId]) REFERENCES [SeriesCollections]([SeriesCollectionId])
Using Entity Framework I have the following:
public DbSet<Page> Pages { get; set; }
public DbSet<Series> Series { get; set; }
public DbSet<Collection> Collections { get; set; }
public DbSet<SeriesCollection> SeriesCollections { get; set; }
public DbSet<Title> Titles { get; set; }
In the view I want to get the following.
For a given 'Page' (id), I want all the 'Series' and within each of those 'Series', be able to list each of the 'Titles' and its associated 'Collection'.
First off - is my db set up correctly? Secondly, I'm struggling with the db call and viewmodels that would return this.
If anyone can help that'd be great
Thanks in advance
The 'Collection's can hold one or more 'Titles'.
Because of this I would modify your DB table schema:
In table Titles replace [SeriesCollectionId] by [CollectionId], directly refering to the Collections table.
In table SeriesCollections remove your PK [SeriesCollectionId] and make instead the remaining two fields [SeriesId] and [CollectionId] to a composite primary key.
Now, you can model a many-to-many relationship between Series and Collections with EF. Then the join table SeriesCollections isn't part of your model anymore. It's just a hidden table in the DB which is managed by EF. Therefore you can remove public DbSet<SeriesCollection> SeriesCollections { get; set; }.
The model classes could then look like this:
public class Page
{
public int PageId { get; set; }
[Required]
[MaxLength(50)]
pubic string Title { get; set; }
public ICollection<Series> Series { get; set; }
}
public class Series
{
public int SeriesId { get; set; }
[Required]
[MaxLength(50)]
pubic string Title { get; set; }
public int SeriesId { get; set; }
public int PageId { get; set; } // FK property, helpful but not required
public Page Page { get; set; }
public ICollection<Collection> Collections { get; set; }
}
public class Collection
{
public int CollectionId { get; set; }
[Required]
[MaxLength(50)]
pubic string Title { get; set; }
public ICollection<Series> Series { get; set; }
public ICollection<Title> Titles { get; set; }
}
public class Title
{
public int TitleId { get; set; }
[Required]
[MaxLength(100)]
pubic string TTitle { get; set; } // must be other name then class
public int CollectionId { get; set; } // FK property
public Collection Collection { get; set; }
}
For many-to-many mapping you need Fluent API:
public class MyContext : DbContext
{
public DbSet<Page> Pages { get; set; }
public DbSet<Series> Series { get; set; }
public DbSet<Collection> Collections { get; set; }
public DbSet<Title> Titles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Series>()
.HasMany(s => s.Collections)
.WithMany(c => c.Series)
.Map(a =>
{
a.MapLeftKey("SeriesId");
a.MapRightKey("CollectionId");
a.ToTable("SeriesCollections");
});
}
}
EF will figure out all other relationships by convention, I believe.
For a given 'Page' (id), I want all the 'Series' and within each of
those 'Series', be able to list each of the 'Titles' and its
associated 'Collection'.
With the model above you could then try:
var page = context.Pages.Where(p => p.PageId == id)
.Include(p => p.Series.Select(s => s.Collections.Select(c => c.Titles)))
.SingleOrDefault();
It would select the page which contains a list of series with a list of collections with a list of titles.
Not sure if this is exactly what you want, just an untested starting point.
(BTW: You can write your classes first (Code-First) and let EF create your database tables. It's easier during design phase when you want to try some mappings, imo.)
Edit
One thing I forgot: If you really want non-variable fixed length string fields (NCHAR(50)) you must define this explicitely in Fluent API. By default EF would assume NVARCHAR(50) fields with the mapping above. Setting to fixed length columns would look like this:
modelBuilder.Entity<Page>().Property(p => p.Title).IsFixedLength();

Resources