ADO.NET Entities not picking up an FK relationship - entity-framework

I've got a table "Persons" (PersonId, Name, Address) which contains information about people. I then subclass this information with tables "Clients" (PersonId, DateJoined) and Victims (PersonId, DateAssassinated).
In SSMS I have established an FK relationship FK_Clients_Persons and FK_Victims_Persons where the Primary Key is Persons.PersonId and the foreign key is the eponymous field in the Clients and Victims tables respectively. In SSMS I cannot see any obvious functional difference between these relationships.
However, in ADO.NET Entities when I create the model from the database, the tool does not identify FK_Victims_Persons but it does recognise FK_Clients_Persons. It just treats Victims.PersonId as a simple field and doesn't generate relationship members for it. The missing FK relationship does not appear in the Constraints tree of the Model Browser, but the other one does.
I have no idea why this is, has anyone faced this problem before?
No matter how many times I start over, I can't get it to work.

Related

Entity Framework: Doing JOINs without having to creating Entities

Just starting out with Entity Framework (Code First) and I have to say I am having a lot of problems with it when loading SQL data that is fairly complex. For example, let's say I have the following tables which stores which animals belongs to which regions in the world and the animal are also categorized.
Table: Region
Id: integer
Name string
Table AnimalCategory
Id integer
Name: string
RegionId: integer -- Refers back Region
Table Animal
Id integer
AnimalCategoryId integer -- Refers back AnimalCategory
Let's say I want to create a query with Entity Framework that would load all Animals for a specific region. The easiest thing to do is to create 3 Entities Region, AnimalCategory, and Animal and use LINQ to load the data.
But let's say I am not interested in loading any AnimalCategory information and define an Entity class just to represent AnimalCategory so that I can do the JOIN. How can I do this with Entity Framework? Even with many of its Mapping functions I still don't think this is possible.
In non Entity Framework solutions this is easy to accomplish by using INNER JOINs in SPs or inline SQL. So what are my options in Entity Framework? Shall I pollute my data model with these useless tables just so I can do a JOIN?
It's a matter of choice I guess. EF choose to support many-to-many associations with transparent junction tables, i.e. where junction tables only have two foreign keys to the associated entities. They simply didn't choose to support this far less common "skipping one-to-many-to-many" scenario in a similar manner.
And I can imagine why.
To start with, in a many-to-many association, the junction table is nothing but that: a junction, an association. However, in a chain of one-to-many (or many-to-one) associations it would be exceptional for any of the involved tables to be just an association. In your example...
Animal → AnimalCategory → Region
...AnimalCategory would only have a primary key (Id) and a foreign key (RegionId). That would be useless though: Animal might just as well have a RegionId itself. There's no reason to support a data model that doesn't make sense.
What you're after though, is a model in which the table in the middle does carry information (AnimalCategory.Name), but where you'd like to map it as a transparent junction table, because a particular class model doesn't need this information.
Your focus seems to be on reading data. But EF has to support all CRUD actions. The problem here would be: how to deal with inserts? Suppose Name is a required field. There would be no way to supply its value.
Another problem would be that a statement like...
region.Animals.Add(animal);
...could mean two things:
add an Animal and a new AnimalCategory, the latter referring to the Region.
Add an Animal referring to an existing AnimalCategory - without being able to choose which one.
EF wouldn't want to choose for some default behavior. You'd have to make the choice yourself, so you can't do without access to AnimalCategory.

Why can't I have a referential constraint with a one to zero-to-one association?

I'm using entity framework 4.3 model first and can't figure out why I'm not allowed to have a one to zero-to-one association along with a referential constraint.
I have two main problems. I can't force referential integrity (without manual intervention) and my lazy loading doesn't seem to work... all my 1 to many associations are fine.
I basically have two tables, Loans and Contracts. The Contracts table has a scalar field for LoanId.
Until a loan is submitted, it does not have contract data and I chose not to place everything in the same table due to the size of the contract data. Ie. I don't want contract data retrieved from the database unless it is actually required.
I've searched around and can't seem to find any model first information that clearly answers my questions. Any information that may help me understand and clarify my problem would be greatly appreciated.
Regards
Craig
I guess LoanId field is not a primary key in Contracts table. In such case you cannot have such one-to-one relation because EF doesn't support it. When you create LoanId field in Contracts table the only way to force one-to-one relation is to add unique constraint on that field. EF currently doesn't support unique keys (except primary keys) so the only way to create one-to-one relation is to create relation between primary keys (Loan.Id <-> Contract.Id). If you don't follow this you will get error in designer.

Why does DBIx::Class not create many-to-many accessors?

While creating a schema from a database many-to-many relationships between tables are not created.
Is this a principal problem?
Is it possible to detect from the table structure that many-to-many relationships exist and create the respective code in schema classes automagically?
It is indeed a somewhat fundamental problem -- many_to_many is a "relationship bridge" and not a "relation." The documentation explains that "the difference between a bridge and a relationship is, that the bridge cannot be used to join tables in a search, instead its component relationships must be used."
On the other hand, this means that if the real relationships are correctly discovered it should be straightforward to add the many-to-many relationships automatically: First, search for tables that have two or more has_many relationships. Then, for each pair of such relationships, create a many-to-many relationship bridge. (Of course, one might hope that DBIx::Class would do this itself.)
The problem with developing this kind of code is that many tables that contain multiple references are not many-to-many tables, and have multiple references for other reasons. For instance, I'll make up a schema for some fictional app where something could be regarded as a many-to-many table, when it is not.
create table category (
id primary key,
...
);
create table sub_category (
id primary key,
category references category(id),
...
);
/* EDIT:
This is the table that could be regarded as many_to_many
by an automated system */
create table product (
id primary key,
category references category(id),
sub_category references sub_category(id),
...
);
Something could be built this way for ease of use, without having to do multiple table joins in the database on a website, especially when considering speed. It would be difficult for a piece of code to say definitively 'this is not a many_to_many' situation, while the developer should be able to easily figure it out, and add in the many_to_many line below the checksum.
I consider DBIX::Class schema outputs a good starting point, and little more, especially when working with auto numbering in non-MySQL databases, among other things. I often need to modify above the "Don't modify above this line" stuff (although many_to_many can obviously go below that checksum, of course.

Trouble inheriting from another entity

I'm having trouble configuring entity relationships when one entity inherits from another. I'm new to ADO Entity Framework -- perhaps someone more experienced has some tips for how this is best done. I'm using .net 4.
Database tables with fields:
Products (int ID, nvarchar Description)
FoodProducts (int ProductID, bit IsHuge)
Flavors (int ID, int FoodProductID, nvarchar Description)
There are constraints between Products and FoodProducts as well as FoodProducts and Flavors.
Using the designer I create a model from the database. The designer seems to get it right, with a 1:0..1 association between Product and FoodProduct entities, and 1:* association between Flavor and FoodProduct. No errors when I save or build.
Next I set FoodProduct entity to inherit from Product entity. Then I get errors concerning relationship between Product and FoodProduct. Ok, starting fresh, I first delete the relationship between Product and FoodProduct before setting the inheritance. But now I get errors about the relationship between FoodProduct and Flavor. So I delete and then recreate that relationship, connecting Flavor.ID to FoodProduct.ProductID. Now I get other errors.
My question is this: Should I instead be creating relationship between Flavor.FoodProductID and Product.ID? If so, I assume I then could (or should) delete the FoodProduct.ProductID property. Since my database will have many of these types of relationships, am I better off first creating the entity model and exporting the tables to SQL, or importing the database schema and then making many tweaks?
My intent is that there will be several types of products, some of which require many additional fields, some of which do not. So there may be zero or one FoodProducts records associated with each Product record. At least by my thinking, the table for each sub-type (FoodProducts) should be able to "borrow" the primary key from Products (as a FK) to uniquely identify each of its records.
You can find a screen capture here: http://img218.imageshack.us/img218/9720/entityframework.jpg (I'd embed the img but haven't earned the requisite rep' yet!)
Well, I deleted the FoodProduct.ProductID field, as it should always return the same value as Product.ID anyway. Then, as you hinted, I had to manually map the Products.ID field to FoodProducts.ProductID field. Errors resolved. I'll write a little code to test functionality. Thanks for the "observations"!
Couple of observations:
FoodProducts needs a primary key (e,g identity - FoodProductID). Are you sure it should be a 1:0..1 between Food and FoodProducts? I would have thought it should be 1:0..*. For this cardinality to work you need a unique PK on this table.
When you setup inheritance for entities, the parent entity's properties are inherited. So FoodProducts will inherit ID from the Product table.
BUT, on the physical model (database), this field still needs to be mapped to a column on the FoodProducts table - which is why you need the identity field.
After you setup inheritance, you still need to map all the columns on the derived tables. My money is on you have not mapped "ID" on FoodProducts to any column.
If you screencapped your model and show the errors you are getting it would be much easier to diagnose the issue.

Entity Framework - Change Relationship Multiplicity

I have a table [User] and another table [Salesperson] in my database. [Salesperson] defines a unique UserID which maps to [User].UserID with a foreign key. When I generate the model with Entity Framework I get a 1-to-Many relationship between [User]-[Salesperson], meaning that each User has a "Collection of Salesperson", but what I want is a 0..1-to-1 relationship where each User has a nullable reference to a "Salesperson".
I tried fiddling around with the XML and changing the association's multiplicity settings, but that only produced build errors. What I am trying to achieve is no different than having a nullable SalespersonID in [User] that references [Salesperson].SalespersonID, but because salespeople only exist for specific users it feels like I'd be muddying up my [User] table structure just to get the relationship to point the right way in Entity Framework.
Is there anything I can do to change the multiplicity of the relationship?
Make the PK of Salesperson itself a FK to User. The EF's GUI designer will then get the cardinality correct, since PKs are unique.