I have created a model in the name of Sample with an Id and DocumentId property.In this I don't mention primary key for Id property.But it forms the primary key when I created the Sample as table in entity framework.I want to remove the primary key for Id. What do I have to do. Please help me. I am very new to mvc4.
public class Sample
{
[Required,DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
public int DocumentId { get; set; }
}
public override void Up()
{
CreateTable(
"dbo.Samples",
c => new
{
Id = c.Int(nullable: false, identity: false),
DocumentId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id);
}
I am putting this here as I don't think it will show up very well in comments :)
In the case of a user having many roles (and each role possibly being played by many users), you would have three tables linked to 2 classes. The tables would be a Users table with a unique UserId column and the rest of the user details. Another table would be Roles with a unique RoleId and the rest of the role information and a joining table that would have the id of the user and the id of the role he plays (this table could have a unique id of itself). If the user has 2 roles, they would have 2 records in the joining table, one for each of the roles. The classes would look something like this:
public class User{
public long UserId {get;set;}
public ICollection<Role> roles{get;set;}
//Other properties of the user name, DOb,etc.
}
public class Role{
public long RoleId{get;set;}
public ICollection<User> Users{get;set;}
//other properties of Role
}
This is a many to many relationship. Of course you could also have it as a one to many relationship if the role can be played by one user. In that case you don't need the joining table and you can just add a UserId column to the Role table and instead of a collection of users, the role would have a single property of type user (not really needed unless you want to navigate back from role to user).
Try adding the NotMapped attribute in your Id.
public class Sample
{
[Key]
public int SampleId {get;set;}
[Required,DatabaseGenerated(DatabaseGeneratedOption.None)]
[NotMapped]
public int Id { get; set; }
[Required]
public int DocumentId { get; set; }
}
EDIT:
I added a key attribute to specify your primary key.
You can also try this, which I think is better:
public class Sample
{
public int SampleId {get;set;}
public virtual ICollection<Document> Documents {get;set;}
}
public class Document
{
public int DocumentId {get;set;}
public int SampleId {get;set;}
public virtual Sample Sample {get;set;}
}
virtual keyword is for lazy loading.
Open the entity diagram (.edmx) file and find which ever property in that particular table is the primary key. Right click on it and select "properties". In the properties window see where it says StoreGeneratedPattern - Identity? Change that to none and save the diagram. It will regenerate the .cs model files by itself
Fluent API suppresses the Data Annotations in Entity framework. Data Annotation for Primary is [Key] and ID is by default Primary key with identity.
In that scenario, Delete(if it's there) Data Annotation of ID i:e;[KEY] and use Fluent API in your context class. In below example, my primary key is "CustomerName" due to Fluent. Example:
public class Customer
{
public int CustomerName { get; set; }
public int ID { get; set; }
[Required]
public string ProductID { get; set; }
}
In Context Class:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>().HasKey(s => s.CustomerName);
}
Related
This is what i am trying to achieve :
modelBuilder.Entity<ApplicationUser>()
.HasMany(u => u.Following)
.WithMany(u => u.Followers)
.Map(m =>
{
m.ToTable("FollowTables");
m.MapLeftKey("UserId");
m.MapRightKey("FollowId");
});
In application user class, i have configured following and followers like this:
public ICollection<ApplicationUser> Following { get; set; }
public ICollection<ApplicationUser> Followers { get; set; }
follow table should be something like this:
public class FollowTable
{
[Key]
public int autoId { get; set; }
public int UserId { get; set; }
public int? FollowId { get; set; }
}
autoId is primary key and UserId and FollowId both are foreign key to ApplicationUser class where UserId is user's own id and FollowId are the ids which user is following.Its data could be following:
autoId UserId FollowId
1 4 11
2 4 12
3 4 13
Now, i problem is when i update database through pmc, it is creating two database tables one is FollowTables with column (USerId, FollowId) and one is FollowTables1(autoId, USerId, FollowId).
If i remove this line from applicationDbContext class:
public DbSet<FollowTable> FollowTables { get; set; }
then its creating only one table but with no primary key.
please someone help me out . how to properly configure UserId and followId as foreign key and these two should map to ApplicationUser's Id.
I want to use those Collection's following and Followers too.how to do it.
You have to decide if you want to work with an entity that represents the junction table or not. If you don't need to add any other properties to that table, excluding the FKs, then I suggest you don't map the junction table as entity. It is going to be more easy for you due to Entity Framework will handle that table for you.
Now if you really need to map that table then you need to delete many-to-many fluent api configuration and change the type of your navigation properties:
public ICollection<FollowTable> Following { get; set; }
public ICollection<FollowTable> Followers { get; set; }
That is going to create two one-to-many relationships with the junction table, an explicit representation of a many-to-many relationship. To do that you also need to do some changes in that entity:
public class FollowTable
{
[Key]
public int autoId { get; set; }
public int UserId { get; set; }
[ForeignKey("User")]
public ApplicationUser User{ get; set; }
[ForeignKey("Follow")]
public int? FollowId { get; set; }
public ApplicationUser Follow{ get; set; }
}
Also, I don't think FollowId Fk property should be a nullable FK, because you want to represent a relationship between two persons.
If you ask my opinion about what option you should take, I suggest you don't map the junction table if you are going to have only those properties.
I have a couple of classes (for this example anyway) that use code first with the entity framework to connect to the database.
public class Customer
{
[Key]
public long CustomerId { get; set; }
public string CompanyName { get; set; }
...
public virtual List<Contact> Contacts { get; set; }
}
public class Contact
{
[Key]
public long ContactId { get; set; }
public string Forename { get; set; }
...
public long CustomerId { get; set; }
public virtual Customer Customer { get; set; }
}
When I hook these up in my context class directly to the db the foreign key relationships hook up fine and I can access the collection of contacts from within the customer class.
class RemoteServerContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Contact> Contacts { get; set; }
...
}
My problem is that these database tables are used by various different systems and are massive. In order to increase efficiency I have overridden the default behaviour to point at a view (and also a stored proc elsewhere) rather than directly at the table.
public IEnumerable<Customer> Customers ()
{
return Database.SqlQuery<Customer>("SELECT * FROM vw_CustomerList");
}
public IEnumerable<Contact> Contacts()
{
return Database.SqlQuery<Contact>("SELECT * FROM vw_ContactsList");
}
I have made sure that in each of the views I have included the foreign key fields: CustomerId and ContactId.
When I do this however the class joins appear to be lost - there's always a null when I drill into either of the objects where it should be pointing to the other one. I have tried to set up what the foreign key field should point to but this doesn't seem to help either.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>().HasRequired(p => p.Customer)
.WithMany()
.HasForeignKey(k => k.CustomerId);
}
Is there a way to establish the connection when overriding the default behaviour?
There is no overriding in this case. If you removed
public DbSet<Customer> Customers { get; set; }
and replaced it with
public IEnumerable<Customer> Customers ()
{
return Database.SqlQuery<Customer>("SELECT * FROM vw_CustomerList");
}
you have completely changed the behavior. The first uses entities and full power of EF. The second is only helper to execute custom SQL. Second without first or without defining entity in OnModelCreating doesn't use Customer as mapped entity at all - it uses it as any normal class (only mapped entities can use features like lazy loading).
Because your Customer is now mapped to view you cannot use your former Customer class used with table. You must define mapping of Customer to a view by cheating EF:
modelBuilder.Entity<Customer>().ToTable("vw_ContactsList"); // EF code fist has no view mapping
Once you have this you can try again using:
public DbSet<Customer> Customers { get; set; }
Unless your view is updatable you will get exception each time you try to add, update or delete any customer in this set. After mapping relation between Customer and Contact mapped to views your navigation properties should hopefully work.
The problem with SqlQuery is the way how it works. It returns detached entities. Detached entities are not connected to the context and they will not lazy load its navigation properties. You must manually attach each Customer instance back to context and to do that you again need DbSet.
I've been trying to create model in EF 4.1 to represent a database schema with a single table and column holding foreign keys from two other tables, but have had little luck with both annotations and the fluent API. A sample model is shown here:
public class User
{
...
public virtual ExtendedAttribute ExtendedAttributes { get; set; }
}
public class Account
{
...
public virtual ExtendedAttribute ExtendedAttributes { get; set; }
}
public class ExtendedAttribute
{
public Guid Id {get; set;}
public Guid ItemId {get; set;} // both Account.Id and User.Id stored here
public string Value { get; set; }
}
Currently the configuration for these entities looks something like this for both User and Account modelBuilders:
this.HasOptional(u => u.ExtendedAttributes).WithRequired();
Any thoughts on how to do achieve? Many thanks.
It is even not possible with the database itself and EF will not put any abstraction for that. You must have separate column and navigation property for each entity.
First, is there a way to tell EF 4.1 that a column needs to be unique by using either data annotations or the fluent API?
Second, regarding navigation properties, I have have 2 classes Document and User. In the document class I have a property for the OwnerId (UserId) and a property for Owner (User). How do I tell EF 4.1 that the OwnerId is really UserId and Owner is a navigation property back to User?
The Document Class:
public abstract class Document: BaseEntity
{
public bool IsActive { get; set; }
public string Description { get; set; }
//The UserId
public Guid OwnerId { get; set; }
//The User
public User Owner { get; set; }
}
Entity framework doesn't support unique keys at all so the answer to your first question is no.
OwnerId should be recognized as foreign key for Owner automatically unless you map to existing database where the foreign key is named differently. In such case you can use for example:
public abstract class Document: BaseEntity
{
public bool IsActive { get; set; }
public string Description { get; set; }
[Column("UserId"), ForeignKey("Owner")]
public Guid OwnerId { get; set; }
public User Owner { get; set; }
}
Foreign key data annotation is probably not needed but you can use it to explicitly pair your FK property with navigation property.
In fluent mapping you can use:
modelBuilder.Entity<Document>()
.Property(d => d.OwnerId)
.HasColumnName("UserId");
modelBuilder.Entity<Document>()
.HasRequired(d => d.Owner)
.WithMany(...)
.HasForeignKey(d => d.OwnerId);
I am using EF4 code first and want to generate a composite key which is made of a class property and foreign key. I have two classes: Order and Company. The Order class holds a reference but this will not necessarily be unique between companies. So I intend to use a composite key made up of Reference and Company.CompanyId.
I have tried using the following to set it but I get an error message "Key expression is not valid".
modelBuilder.Entity<Order>().HasKey(o => new { o.Reference, o.Company.CompanyId });
I have also tried
modelBuilder.Entity<Order>().HasKey(o => new { o.Reference, o.Company });
and this fails.
these are my classes:
public class Order
{
public string Reference { get; set; }
public Company Company { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public virtual ICollection Orders { get; set; }
}
Any help would be greatly appreciated.
As Antony Highsky mentioned, you can only use scalar properties in the key.
So, you will need to add a foreign key (scalar property) to the Order class and associate it with the navigation property Company as shown below:
public class Order
{
public string Reference { get; set; }
public int CompanyId { get; set; }
[RelatedTo(ForeignKey = "CompanyId")]
public Company Company { get; set; }
}
And then create the composite key using the model builder:
modelBuilder.Entity<Order>().HasKey(o => new { o.Reference, o.CompanyId });
Note that data annotations (RelatedTo attribute) were introduced with the Entity Framework CTP 3. For another option that only uses data annotations instead of HasKey method, see this post:
http://www.luisrocha.net/2010/11/creating-composite-keys-using-code.html
One thing that doesn't look quite right is your use of the non-generic version of ICollection. Try this:
public virtual ICollection<Order> Orders { get; set; }
Did you try this?
modelBuilder.Entity().HasKey(o =>o.Reference );
modelBuilder.Entity().HasKey(o =>o.CompanyId );
According to this source, only scalar properties are allowed in the key. Navigation properties are not.