I have a table which has the Id as primary key, I want to have a composite unique key on Code and Value column. I'm trying in this way.
[Table("Test")]
public class Test: FullAuditedEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public virtual int Code { get; set; }
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public virtual int Value { get; set; }
But it's making the composite primary key not unique key.
Try this:
public class SomeClass : Entity<int>
{
[Column("Code")]
public override int Id {get; set;}
public virtual string Name { get; set; }
}
[DatabaseGenerated(DatabaseGeneratedOption.None)] will make the Database to NOT create the Code column. What you need in reality is to override the Id and rename it to Code.
And to have a composite key, simply add
[Key]
public virtual int Value { get; set; }
field.
Adding solution for others.
Don't modify anything just add the below line
modelBuilder.Entity<Test>(b =>
{
b.HasIndex(e => new { e.Code, e.Value}).IsUnique();
});
Related
after googling for a while, i haven't seen an example on how to create a table with a foreign key with the nuget sqlite-net-pcl for my xamarin.forms app.
Let's say i have GroupTask.cs in which i storethe initial GroupTask:
[Table("GroupTask")]
public class GroupTask
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Topic { get; set; }
public DateTime Date { get; set; }
}
Now i want to create Task.cs which will be used in each GroupTask ( GroupTask contains multiple task). But how do i set it up if possible ?
[Table("Task")]
public class Task
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string Duration { get; set; }
}
Is it possible with sqlite-net-pcl ? Thanks.
Note: Technoligies in use are ASP.Net MVC 3, Entity, SQL Server Management Studio
Problem?
It seems that when I run, the context as: public class DatabaseInit : DropCreateDatabaseAlways<LocationAppContext>
That it creates the database, but my service assignments table has an extra foreign key called
ServiceAssignment_Service when it shouldn't.
My service assignment model is as such:
namespace LocationApp.Models
{
public class ServiceAssignment
{
public int id { get; set; }
public int locationID { get; set; }
public int ServiceID { get; set; }
public virtual Location Location { get; set; }
public virtual ServiceAssignment Service { get; set;}
}
}
and the service model is as such:
namespace LocationApp.Models
{
public class Service
{
public Service()
{
this.ServiceAssignments = new HashSet<ServiceAssignment>();
}
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public bool active { get; set; }
public string icon { get; set; }
public virtual ICollection<ServiceAssignment> ServiceAssignments { get; set; }
}
}
with that said, the relation ship is simple:
service assignments have many location id's and service id's.
why is this extra foriegn key being generated? the curent keys, that should e there is:
PK: Main PK for the table
FK 1: Location_ServiceAssignment
FK 2: Service_ServiceAssignment
Those are their, how ever this third one is baffling....
The second part is: If a location of id 2 has a service id of 2,3,6,7 How do I get all service id's returned, such that I can pass the object to a service query to get all information on the service based on the ID?
Update:
Context Class:
namespace LocationApp.DAL
{
public class LocationAppContext : DbContext
{
public DbSet<Content> Contents { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<ServiceAssignment> ServiceAssignments { get; set; }
public DbSet<Service> Services { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Location>().HasMany(sa => sa.ServiceAssignments);
modelBuilder.Entity<Service>().HasMany(sa => sa.ServiceAssignments);
}
}
}
I think you have to tell EF that Service.ServiceAssignments is the inverse navigation property of ServiceAssignment.Service and that Location.ServiceAssignments is the inverse of ServiceAssignment.Location. Right now with your mapping you only specify that Location or Service has many ServiceAssignments. EF will consider the navigation properties in ServiceAssignment as the ends of separate relationships.
Try instead the mapping:
modelBuilder.Entity<Location>()
.HasMany(l => l.ServiceAssignments)
.WithRequired(sa => sa.Location)
.HasForeignKey(sa => sa.LocationID);
modelBuilder.Entity<Service>()
.HasMany(s => s.ServiceAssignments)
.WithRequired(sa => sa.Service)
.HasForeignKey(sa => sa.ServiceID);
You can probably remove this mapping altogether as an alternative because EF should detect the right relationships by convention.
So, use either no mapping (=mapping by convention) or the full mapping (=specifying both ends of the relationships). Just the 50%-mapping you have used is likely the problem.
I have read the articles about Independent association from Ladislav. I have checked the information he provided in this link.
The information is quite helpful and it shed some light.
However I want to model my existing database which I was given access to. It has three tables Users, Certificates and Quiz .
At first I thought of modeling as independent association. Why? My Users table has primary key UserID and Certificates table has PK CertID and a column UserID which I can say is a foreign key. Just when I thought its a one to many relationship, I realized that some UserID in Users table are not found in Certificates table. However all UserID in Certificates can be found in Users table.
My question is should I use independent association and if so how to achieve this that my Users table become the principal class and the Certificates one the dependent. This is so that I can show or have values from my Users table then read values from my Certificate table in my asp.net mvc 3 application.
Please correct this code below which shows what I intend to achieve what I stated above:
public class Certificates
{
[Key]
public Users CertID { get; set; }
public int ID { get; set; }
public DateTime recvd { get; set; }
public int QuizID { get; set; }
}
public class Users
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string email { get; set; }
public ICollection<Certificates> Certificates { get; set; }
}
public class Quiz
{
public int QuizID { get; set; }
public string QuuizName { get; set; }
public int VolumeNo { get; set; }
public int mark { get; set; }
public ICollection<Certificates> Certificates { get; set; }
}
public class cpdContext : DbContext
{
public DbSet<Certificates> Certificates { get; set; }
public DbSet<Users> Users { get; set; }
public DbSet<Users> Quiz { get; set; }
Finally how do I show details view with information from these three classes with ability to add Users mark and tests. The relationship I want to model is 1 to many between Quiz and Certificates.
My Users table has primary key UserID and Certificates table has PK
CertID and a column UserID which I can say is a foreign key. Just when
I thought its a one to many relationship, I realized that some UserID
in Users table are not found in Certificates table. However all UserID
in Certificates can be found in Users table.
That's pretty normal for a one-to-many relationship where User is the principal and Certificate the dependent and you have a constraint enforced for the relationship.
I don't see this as an argument to decide for independent or foreign key associations. As far as I can tell you can map a database schema with both association types. The database schema shouldn't be the driving factor for the decision. Ladislav's posts you have linked explained it in all details. There are other points than the database schema that will guide the decision:
Architecture: Strict separation of object and relational world which might lead to the decision that you don't want a "foreign key" property as a relational artifact in your object model. This goes in favor of independent associations.
Ease of use: The additional foreign key property makes it easier to work with relationships, especially updating them, in some scenarios. This point is for foreign key associations.
Performance: EF is faster with foreign key associations in some situations with larger models.
Personally point 2 above tips the scales for me in most cases, but as said both is possible.
Mapping with foreign key associations (I omit all properties except PK, FK and navigation properties to keep it short):
public class Certificates
{
[Key]
public int CertID { get; set; }
[ForeignKey("User")]
public int UserID { get; set; }
[ForeignKey("Quiz")]
public int QuizID { get; set; }
public Users User { get; set; }
public Quiz Quiz { get; set; }
}
public class Users
{
public int ID { get; set; }
public ICollection<Certificates> Certificates { get; set; }
}
public class Quiz
{
public int QuizID { get; set; }
public ICollection<Certificates> Certificates { get; set; }
}
This assumes that both relationships are required, i.e. FKs in the database are not nullable. If they are you need to make the FK properties nullable as well (int?). Instead of data annotations you can use Fluent API, similar (but not exactly identical!) to the following example.
Mapping with independent associations:
public class Certificates
{
[Key]
public int CertID { get; set; }
public Users User { get; set; }
public Quiz Quiz { get; set; }
}
public class Users
{
public int ID { get; set; }
public ICollection<Certificates> Certificates { get; set; }
}
public class Quiz
{
public int QuizID { get; set; }
public ICollection<Certificates> Certificates { get; set; }
}
public class cpdContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entitiy<Users>()
.HasMany(u => u.Certificates)
.WithRequired(c => c.User) // or WithOptional
.Map(m => m.MapKey("UserID")); //<- DB FK column name
modelBuilder.Entitiy<Quiz>()
.HasMany(u => u.Certificates)
.WithRequired(c => c.Quiz) // or WithOptional
.Map(m => m.MapKey("QuizID")); //<- DB FK column name
}
}
The navigation properties in Certificates are not required (neither in the first nor the second example), you can remove them, if you don't need them, just use the parameterless WithRequired() then, and use Fluent API in the first example. (Possibly a [ForeignKey("UserID")] annotation on the Certificates collection in the Users class will work as well.)
Models:
public class Status
{
public int Id { get; set; }
}
public class Podcast
{
public int Id { get; set; }
public virtual Status Status { get; set; }
}
The Podcast table has the StatusId column, and this column is a foreign key. In this case I've got the following error message: Invalid column name 'Status_Id'. Why? - Many times I faced that articles with such examples. This is the first question.
Ok, no problem - i've added an underscore character to these columns: Sttaus_Id and so on.
Now it seems that everything works fine, but when I modify my model by the following way:
public class Podcast
{
public int Id { get; set; }
public int Status_Id { get; set; }
public virtual Status Status { get; set; }
}
Now I get the following error: Invalid column name 'Status_Id1'.
Why? I can't use the DropDownListFor helper without these xx_id properies.
I believe the issue here is that you have created your DB first and created a column named StatusId for your FK reference but you haven't told EF that you are using a non-default column name for your FK.
the following will give you the structure you are after (ps i agree with your naming convention i personally dislike the _ in fk ids)
public class MyContext : DbContext
{
public DbSet<Podcast> Podcasts { get; set; }
public DbSet<Status> Status { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Podcast>().HasOptional(p => p.Status)
.WithMany().HasForeignKey(p => p.StatusId);
base.OnModelCreating(modelBuilder);
}
}
public class Status
{
public int Id { get; set; }
}
public class Podcast
{
public int Id { get; set; }
public int? StatusId { get; set; }
public virtual Status Status { get; set; }
}
The convention at least for the foreign key field is table name + field name, so in your case StatusId without the underscore. But I'm not sure why it says invalid column name Status_Id1.
Remove the underscore, and try again. If you still get an error message, please make an edit to your question with the results.
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();