Many to Many relationship with 2 keys in one table - asp.net

I am building an ASP.net application and I am using the Entity framework DBFirst. I have 2 tables. One table has 2 keys. The other table has 1 key. So the table structure;
Topic Table
> Id
> ArticleId
> ...
Branch Table
> Id
> ...
I have a problem creating a many to many relationship since there are 2 keys in the topic table. My many to many relation table looks like this;
BranchTopic
> TopicId
> BranchId
How do I solve this? I want a many to many relationship between the Topic and Branch. I don't want any relationship in between the ArticleId in this relationship. When I leave out the ArticleId visual Studio shows the following error;
Error 15 Error 3024: Problem in mapping fragments starting at line 503:Must specify mapping for all key properties (Id, ArticleId) of End Topic in Relationship MathematicsBranchTopic.
C:\Users\Username\documents\visual studio 2013\Projects\Mathematics\Mathematics\Model.edmx 504 11 Mathematics

You just need to specify column order to specify multiple keys
From the documentation:
public class Passport
{
[Key]
[Column(Order=1)]
public int PassportNumber { get; set; }
[Key]
[Column(Order = 2)]
public string IssuingCountry { get; set; }
public DateTime Issued { get; set; }
public DateTime Expires { get; set; }
}

Related

SQLite-Net Extensions | Foreign Key Reference to same entity

I am facing an issue in using SQLite-Net Extensions to save data in local DB in scenario where the foreign key is referencing the same entity (self-join).
Example – Employee and Manager. Every employee has a manager and a manager is also an employee. I am facing issues in saving data in such cases. It will be really helpful if you can provide some insights. Does this extension support this kind of relationship?
Yes, relationships between objects of the same class are supported, but the foreign keys and inverse properties must be explicitly specified in the relationship property attribute because the discovery system will get it wrong as there are be two relationships with the same type.
This example is extracted from the project readme:
public class TwitterUser {
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
[ManyToMany(typeof(FollowerLeaderRelationshipTable), "LeaderId", "Followers",
CascadeOperations = CascadeOperation.CascadeRead)]
public List<TwitterUser> FollowingUsers { get; set; }
// ReadOnly is required because we're not specifying the followers manually, but want to obtain them from database
[ManyToMany(typeof(FollowerLeaderRelationshipTable), "FollowerId", "FollowingUsers",
CascadeOperations = CascadeOperation.CascadeRead, ReadOnly = true)]
public List<TwitterUser> Followers { get; set; }
}
// Intermediate class, not used directly anywhere in the code, only in ManyToMany attributes and table creation
public class FollowerLeaderRelationshipTable {
public int LeaderId { get; set; }
public int FollowerId { get; set; }
}
As you can see here we have a many-to-many between Twitter users. In your case it will be a one-to-many, so you won't need the intermediate table and you'll need the foreign key (ManagerId for example) in your Person class.

Insert record with relationship using OData

This is what my models looks like
public User
{
public string Id { get; set; }
public string Username { get; set; }
public virtual Group Group { get; set; }
}
public Group
{
public string Id { get; set; }
public string Name{ get; set; }
public virtual ICollection<User> Users { get; set; }
}
I using Azure Mobile TableController which using OData for CRUD.
Now I trying to insert new user by specifying the id of the group but instead it gives me an error which shows that instead of trying to associate it with my user model it trying to create new one:
{
"message": "The operation failed due to a conflict: 'Violation of PRIMARY KEY constraint 'PK_dbo.Groups'. Cannot insert duplicate key in object 'dbo.Groups'. The duplicate key value is (ad934511a82c4b42ae5427b5228737c6).\r\nThe statement has been terminated.'."
}
This is what my post looks like:
POST http://localhost/tables/user?ZUMO-API-VERSION=2.0.0 HTTP/1.1
{
email: 'test#test.com',
password: '#test',
group: {
id: 'ad934511a82c4b42ae5427b5228737c6'
}
}
Relationships are not directly supported in Azure Mobile Apps, but you can apply some workarounds to get it to work. Here's a blog post that walks through the scenario: 30 Days of Zumo.v2 (Azure Mobile Apps): Day 26: Relationship Advice.
The specific problem you're running into is the Entity Framework "detatched entities" problem. See e.g. Many to Many Relationships not saving. The problem is that Entity Framework has not loaded the child item into its context, so it thinks that it needs to insert the child item as well as the parent. (There have been long-standing feature requests in Entity Framework to solve this, but the feature has never been added.)
I just posted a similar answer here: How do I insert entities with a 1:n relationship in Azure App Service

Two foreign keys to same primary table

I have two classes: Customer and Association.
A customer can have an association with many customers. Each association is of a defined type (Family, Friend, etc) i.e Customer A is a friend of Customer B. Customer A is related to Customer C. The type of association is defined by an enum AssociationType.
In order to create this in EF i've defined the following classes
public class Customer
{
public string FirstName {get; set;}
public string LastName {get; set;}
public virtual ICollection<Association> Associations { get; set; }
}
public class Association
{
public int CustomerId { get; set; }
public virtual Customer Customer { get; set; }
public int AssociatedCustomerId { get; set; }
public virtual Customer AssociatedCustomer { get; set; }
public AssociationType AssociationType { get; set; }
}
I've removed the Data Annotations as I was unable to get this to compile. I get the error:
"Model compatibility cannot be checked because the database does not
contain model metadata".
Does anyone have any ideas?
It happens sometimes when an error occurs during database creation. The database schema is created then - except the __MigrationHistory table. When you run your application again EF wants to check against the __MigrationHistory table if the schema is still up-to-date with the model and if that table doesn't exist it throws the exception you are having.
To fix the problem either delete the database manually or set the initializer to DropCreateDatabaseAlways<MyContext> (with Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>()) - only once. After the DB is created set it back to your original initializer.
BTW: For your model you will have to specify explicitly that Customer.Associations is related to Association.Customer, either with data annotations...
[InverseProperty("Customer")]
public virtual ICollection<Association> Associations { get; set; }
...or with Fluent API:
modelBuilder.Entity<Customer>()
.HasMany(c => c.Associations)
.WithRequired(a => a.Customer)
.HasForeignKey(a => a.CustomerId);
Thank you Slauma,
your answer got us going in the right direction.
We added the following configuration to the Association configuration:
HasRequired(x => x.AssociatedCustomer).WithMany().WillCascadeOnDelete(false);

How to deal with Database Column with DEFAULT value in SPA(ASP.NET MVC SPA)

Code First Class:
public class Product
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductId{ get; set; }
[MaxLength(256), Required]
public string ProductName { get; set; }
public DateTime CreatedTime { get; set; }
}
In the database, i give the CreatedTime Column the DEFAULT value "(getdate())",
so that the database will generate a value for us on insert operation.
My Question:
Is there some kind of DataAnnotations/something else that can do the following things:
can tell Entity Framework(Code First Mode) to include CreateTime when Building up the Database;
can tell EF NOT to include CreateTime when Inserting a new column into the Database;
can tell EF to retrieve back all the columns including CreateTime when Selecting from the database.
So that, I can treat the CreatedTime Column in the Client Side the same as the ProductId Column(which is the Identity Column: value Only can be generated by the Database; will NOT be included when Inserting a new column; will be included when Selecting...).
I think it's much more clear now, sorry for the misunderstanding!
Dean

Entity Framework 4 CTP5 TPT inheritance not working for deep hierarchy?

I'm having a problem mapping a a slightly more complicated inheritance relationship using the code-first API in CTP5. When I have this:
Table A
--------
int ID (PK)
Table B
--------
int ID (PK)
varchar Something
public class A {
public int ID { get; set; }
}
public class B : A {
public string Something { get; set; }
}
...everything works just fine. But when I add this:
Table C
-------
int ID (PK)
varchar SomethingElse
public class C : B {
public string SomethingElse { get; set; }
}
...then it errors out with "Invalid column name Discriminator", which implies that EF is getting confused and thinks I'm trying to do a TPH mapping. Has anyone else seen this? Is this a known issues in EF? Do I need to do some special mapping?
Thanks in advance for your help.
as far as I know, hierarchies on multiple levels are not supported in code first.

Resources