mvc entity framework trying to deal with duplicates - asp.net-mvc

So I'm trying to figure out how to handle duplicates, and one way I thought of is like redesignating the type to the same type
eg
public class Employee
{
public int Id {get;set;}
public string Name {get;set;}
public int? RemappingId {get;set;}
public virtual Employee Remapping {get;set;}
}
so, basically, anyone can register but since I can't do any validations on this part if somebody accidentally saves a duplicate Employee, I plan to have some admin page to map the duplicate employee to like a "main" employee.
But I'm getting this error:
unable to determine the principal end of an association between the
types the principal end of this association must be explicitly
configured using either fluent API or data annotations
So I'm not sure if that's the right way of dealing with duplicates, if not please do point me to the right direction. And if it is acceptable, any chance you can help me stop the error?
Thanks!
Much appreciated!

So I'm not sure if that's the right way of dealing with duplicates : Yes, it really is not a good way to do it. and you know it too :)
How I would suggest you do it
As you are working with "Employees" I am assuming there will be some id which will be unique to the Employee, (like an EmployeeID). So by making such an id as a primary key, you can do a simple ifExists check for this and show a appropriate message on the view.
Update :
If there is nothing unique for an employee(not even email or employeeId etc), then according to me your database design is faulty. But that again is my personal opinion.
Hope this helps.

Related

How to map auto increment Id from domain model to entity model in Entity Framework ASP.NET Web API

I am trying to follow DDD for my current project. My question is specifically regarding POST request that contains values for my domain model. To simplify, let's say following is my domain model:
class Person
{
public int Id {get, set};
public string name {get, set};
}
And below is the entity model backing above domain:
class PersonEF
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get, set};
public string name {get, set};
}
Now when I receive a POST request to create a new Person it doesn't contain the Id as it's supposed to be generated by the database. I first map Person to PersonEF using AutoMapper which sets the Id to 0 in PersonEF and hence the INSERT in database fails. So to fix these my options are:
Name Id as something else in Person. If I do this then I would have to write custom mapping just for Id for GET requests.
Make Id nullable (int?) in both Person and PersonEF and this way auto increment will work, but having key as nullable int doesn't sound like a good idea in itself.
So please suggest the best way to do this.
EDIT
My bad. Code was missing context.SaveOrUpdate(). I added that and it's working as expected.
It's hard to say for sure, as the code of most importance, that you should have posted, would be that of your controller action where the mapping and saving occurs. However, I can tell you that the 0 is the default value for an int. This is not due to AutoMapper, or mapping in general, per se. The entity, freshly created, without any other interaction, would still have 0 as the id.
As a result, this should not be causing a problem with saving the entity, or else you'd never be able to save any entity that had an int PK. However, depending on what Entity Framework thinks you're trying to do with the entity, it might cause problems. Namely, you need to make sure that Entity Framework is aware that you're wanting to create this entity and not just update it. Usually, that's achieved by simply adding it to the DbSet:
db.PersonEFs.Add(personEF);
Not sure why you would need to go any farther than that, but if that's not working for some reason, you can be a bit more explicit:
db.Entry(personEF).State = EntityState.Added;
However, really, if you need to do that, there's something else going on that you'd just be masking.

Am I Understanding This Correctly? FK constraint may cause cycles or multiple cascade paths'

I'm struggling to get my head around the sql exception:
FK contstraint may cause cycles or multiple cascade paths
I know there are many posts relating to it here on SO, for example: https://stackoverflow.com/a/852047/1778169 and https://stackoverflow.com/a/17127512/1778169
I have read them a few times, but I still don't understand:
exactly what this error means, and
how I can design models to avoid it
My attempt at understanding - have I got this right?
In the models below, User is required for both ForumThread and ForumPost entities.
Deleting a User will cascade like this: User > ForumThread > ForumPost and also like this: User > ForumPost, thus giving me 'multiple cascade delete paths'.
public class ForumThread
{
public int ID {get;set;}
public int UserID {get;set;}
public User User {get;set;}
public Collection<ForumPost> Posts {get;set;}
}
public class ForumPost
{
public int ID {get;set;}
public int UserID {get;set;}
public User User {get;set;}
public int ForumThreadID {get;set;}
public int ForumThread Thread {get;set;}
}
public class User
{
public int ID {get;set;}
public int UserID {get;set;}
public User User {get;set;}
public Collection<ForumThread> Threads {get;set;}
}
If I have understood this correctly, then how would I design the models so that a User is required for both ForumThread and ForumPost entities?
I'd like the User property on the ForumThread to identify and list threads started by a particular user.
I guess one option would be to select threads by identifying the user who made the first post. But isn't that overly complicated for something that should be quite simple?
Your model is fine (except I don't get why User has a user property and a single Thread instead of a collection of Threads, but I assume it's just a copy-and-paste error). If the business meaning of all relationships is that they are required I would model them as required.
The exception you are facing is not a problem of the model itself but of mapping this model to a particular relational database (SQL Server?). The exception is thrown by the database engine and not by Entity Framework. EF doesn't care about multiple cascading delete paths and other database engines might support them. But the one you are using apparently doesn't.
So, it's a technical limitation of the database system and the best way to solve the problem is disabling cascading delete for some or all relationships with Fluent API (see the second link in your question). I would not adjust the model (like defining some relationships as optional with nullable userID? FKs) to make it "compatible" with the particular database. After all a conceptual model should be - as much as possible - a database ignorant idea.
Of course, disabling cascading delete changes a bit the way how you would delete a user with all threads but there is no way to avoid it. You can't just rely anymore on the database deleting all threads (and posts) automatically when you delete a user. You must delete the user and all his threads manually now by calling DbSet<User>.Remove and DbSet<ForumThread>.Remove in a loop.
I don't know exactly your business requirements, but it seems a bit unusual to me that when a user gets deleted really all of his threads and all posts of those threads (including the posts of other users) get deleted as well. Wouldn't it be more appropriate to assign the threads and posts to some system user like Anonymous or Community? It that case you wouldn't even want to have cascading delete on the User relationships.

ServiceStack URLs for related services

With ServiceStack, I'm looking for ways to access related services by composing the URLs in a manner similar to OData.
An OData example would be a URL like
http://localhost:8080/owind.svc/Categories(2)/Products
This would find all the Products related to Category 2.
An equivalent example with ServiceStack seems to be that you would create a Request DTO for a ProductService and set up Routes something like this:
[Route("/Products")]
[Route("/Products/{Id}")]
[Route("/Categories/{Category}/Products")]
public class Products
{
public string Id { get; set; }
public string Category { get; set; }
}
(Ignore the separations of concerns issues mentioned here, the above attributes at least give a clear idea what I'm asking.)
And then in the ProductService you'd support finding Products either via the primary or foreign key. I see something along these lines used in the Northwind.ServiceModel.Operations.Orders class of the ServiceStack.Northwind.ServiceModel sample project.
So I'm wondering, is this the best and most scalable way that exists to do this sort of thing in ServiceStack, or is there some shortcut I'm missing? Thinking on a scale of creating services supporting hundreds of tables, if there existed some sort of shortcut, and if it didn't come with strings attached, it could be helpful.
I can imagine a system where you could automatically generate routes based on anything in a DTO, though you'd need to do some mapping from DTO property name (usually singular) to route (often plural).
No idea if it would be conceivable to carry this beyond one level either...for example
.../Employee/1/Orders/Customers
which would get you every Customer who has had an Order with Employee #1. The notion of implementing this manually on a large scale seems prohibitive. Not sure if there are SOA arguments to be made for or against, but that would be nice to know as well.
Just to be clear, there should be no assumption of the underlying data store or access libraries.

Entity Framework 4.1 Self Referencing

Given a POCO Product class:
public class Product {
public int ProductId {get;set;}
public string Name {get;set;}
}
how can I enable related products using EF?
Basically, I need to allow product owners to add products that user may also be interested in.
I've tried adapting answer in this question but can't get it to work.
I think I need a link table as a product can have many products a user may be interested.
Many thanks in advance
Well, i must have been doing something wrong earlier. I've re-visited option 1 from this answer and its done exactly what i needed.

Field in mapped entity required

I'm not sure if my problem is solvable in a more or less comfortable way.
There is a class Person which has mapped 'hasOne' a participant.
The person has a birthday but this field is not required on the person itself. But if I would like to add a participant to the person then the birthday is required.
How to get rid of this
move the birthday information to the participant object -> That's how I did it for now, but I think moving person related information to other objects cannot be the final solution
Map the property in both classes -> how to tell the validator when it's required and when not?
Merge the two objects -> for now not allowed
Maybe someone has a better idea, I use the nHibernate Validator and there I configure the validation in the class (where the information 'birthday' is not a property on both - maybe this would be a solution?)
With NHibernate validator attributes as you mentioned. This would be in the Participant class. Would this work for you? It is optional on the base class and nullable as you see (can't change type on overriding)
[NotNull, NotEmpty]
public override DateTime? Birthday { get; set; }
This would still leave field nullable in the DB, but don't see way around this without having a table per class implementation rather than a class per hierarchy fluent implementation. Your domain validation will be there to protect though.

Resources