This question keeps popping up, but I couldn't find anyone doing exactly what I am, so here goes:
I've got a table that can have a relationship to one of many tables. Some have many, and some have one. In all cases it would be optional.
So we have a table of Pictures.
We have Products, Vendors, Users.
Products have a one to many relationship with Pictures (they can upload multiple photos of each product).
Users have a one to one (optional on both sides) with pictures. (If the user uploads a photo, great, if not, no problem)
Vendors have a one to one, similar to Users, except it is relating to a different table.
This works fine with the many relationships, but the one to one doesn't work properly.
I want to have a virtual on both sides but define the nullable ForeignKey only in the Pictures table.
public virtual Picture UserPhoto { get; set; }
And then on the other side:
public virtual User User{ get; set; }
[ForeignKey("User")]
public int? UserID { get; set; }
I like to have the keys available in the code, not just in the database, so I don't want to configure the relationship solely in fluent. But If I add a fluent configuration on top, it will add extra foreign keys.
Without a fluent configuration, we get the dreaded
Multiplicity is not valid in Role 'Picture_User_Source' in relationship 'Picture_User'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
Related
As Microsoft says here :
Owned entities are essentially a part of the owner and cannot exist without it, they are conceptually similar to aggregates
It means in DDD architecture (Domain Driven Design) we can use owned types (or collection of owned types ) as an entity inside an aggregation or as a value object. On the other hand, we know that ValueObject in DDD has no Identity value because of its structure and its Immutability. I want to know if I decide to use the Owned type to implement the value object how can I force it to avoid making Id in the creation table?
For example, as you see in the following picture (that Microsoft mentioned here) when we use a collection of owned types, EF makes an "Id" field in the table that no sense in Address Value Object! How to avoid it? and Is it really a correct option?
That example is from the OwnsMany scenario where it clearly explains that it needs a FK in the table to associate addresses back to their Distributor. How else would an Address record associate back to the Distriburor when loading the entities?
If a Distributor only has 0-1 address then you don't need an OwnerId on Address, the Address' Id column would serve as PK and FK back to the Distributor. EF needs a "Key" on each table to uniquely identify each row. You could possibly avoid an "Id" column by mapping a composite key, essentially:
public class Address
{
[Key, Column(0), ForeignKey("Owner")]
public int OwnerId { get; set; }
[Key, Column(1)]
public string Street { get; set; }
[Key, Column(2)]
public string City { get; set; }
public virtual Distributor Owner { get; set; }
}
A dedicated unique, and DB Generated Id column for the Address table IMO makes more sense than a large, composite key of strings and FK.
Ownership as far as the database is concerned is identical to HasOne / HasMany in the way the schema is laid out & relational rules. What differentiates OwnsMany from HasMany is how EF will allow you to access those owned entities. You cannot have a DbSet<Address>, only access Addresses through it's Distributor. It serves no real purpose except to scratch particular design pattern itches. :)
I need help with a design question using Entity Framework 6.1.3 from a Code-First perspective.
We have tables called "Businesses", "People", and "PhoneNumbers". A business can have one-to-many phone numbers and person can have one-to-many phone numbers. I'm struggling to determine the best way to implement this. The following solutions have been explored but neither strikes me as being the "obvious" solution. Can you please offer advice?
Use a common Phone table to hold numbers for the Business and People.
In this solution, the Phone table would have RI to the People table and to the Business table. The ID fields would be nullable so that when it is a business phone, the participant ID would be null and vice-versa:
public Nullable<int> ParticipantID { get; set; }
public Participant Participant { get; set; }
public Nullable<int> BusinessID { get; set; }
public Business Business { get; set; }
Create separate tables for the Business (BusinessPhone) and Person (PersonPhone) phone numbers. Both phone tables could inherit from the original phone table but each would have separate RI statements to the corresponding Business or Person. This way, neither table would need a nullable key.
For example, the PersonPhone table would look something like:
public class PersonPhone : Phone
{
public int ParticipantID{ get; set; }
public Participant Participant { get; set; }
}
Are either of these solutions best practice? Is there a better solution? What do you recommend?
I will suggest that the best option is to use separate tables for this. Use a common ABC called PhoneNumber, and derive subclasses for each collection parent type, each mapped to their own table (TPC strategy). Or, map the ABC to a common table for the common fields, and referenced tables for the references to Person or Business (TPT strategy).
Coming from an object-oriented background where we often optimize for code-reuse; with inheritance being a strategy for reusing code; and with TPH being the default mapping of inheritance structures in EF; it feels right to have these both in a single table. But looking from the perspective of a DBA, mashing these two concerns together is an abuse of the data structures in the database. Call it "schema-smell". It might work, but you are giving up a lot of what the database can do for you. You're painting yourself into a corner for no good reason.
There are three inheritance strategies; this EF tutorial site has a good rundown. The single-table is TPH. Usually I will use this even though it violates 3rd normal form, because it is simple and performant. In the case where types differ by the other types they reference, though, the denormalization compromises offer diminishing returns.
The main problem as I see it: With one table, you have to figure out a way to mash separate FKs in. With one column and a discriminator (which may not even be legal with EF) you lose the ability to do DRI and cascading deletes. With two columns, you'll have to monitor that one and only one is non-null at any given time. With either solution, you'll be giving up storage space. If the two objects ever diverge--say, you have to add an EmployeeName to BusinessPhone--the problem will only be exacerbated.
So, in this case I would recommend either the table-per-type or table-per-concrete-type strategy over table-per-hierarchy.
The only remaining note is that all three involve compromises. I won't get into all the trade-offs (you should be able to find many discussions of these). There may still be cases where TPH makes the most sense because of a use-case that must perform very well.
I think the best way to go at it is to have a table named 'PhoneNumber'. Both Business and People can have a list of PhoneNumbers.
Ofcourse this is only true if the PhoneNumber is equal for both Business and People. If you would like to add extra properties to a PhoneNumber for People, I would suggest going with your second option.
Having a single table for phone numbers seems like the better option. Could you use some sort of discriminator on your PhoneNumbers entity to avoid having to have two nullable columns?
So you'd have a PhoneNumber class, and an enumerable representing the phone number type. Then your Businesses and People each have a list of PhoneNumber as you've mentioned. Example -
public class PhoneNumber
{
public int PhoneNumberId { get; set; }
public int PhoneNumber { get; set; }
public PhoneNumberType PhoneNumberType { get; set; }
public Participant Participant { get; set; }
}
public enum PhoneNumberType
{
Person,
Business
}
This answer is to a very similar question and seems like an even better option if you want to give it a look.
In my EF 6 Model First application, I have an entity with a many-to-many navigation property to another entity. In the first entity, I need to add several references to the same record in navigation property.
The first entity is a “saleslistItem” and the second entity is “warehouseItem”. Normally there will be a one-to-one relationship here, but exceptionally there will be some bundles where one “saleslistItem” contains several “warehouseItems”. “WarehouseItem” can also be included in several “salesListItems”. At the end of the project, my customer says, testing it, that “saleslistItem” must be able to consist of several “WarehouseItems” of the same kind (like two boxes of smoked ham).
These data is used several places in my code. (ie. doing a sale removes items from the warehouse) If I could just add several the same reference, my code would work without any modifications. But in the implementation of the navigation property the “hashtable”-collection is used, and this collection requires unique entries. Is there a workaround here? Performance is irrelevant as the data amount is small.
If there are no such workaround, is it possible to store values together with the instance of navigation property? Maybe it is implemented as a field in the join-table???
Any other suggestions?
Need a solution so the customer pays the last part of the bill!
So you currently have a 1:1 from SalesListItem toWarehouseItemvia a ForeignKey inSalesListItem`? Sounds like you need:
public class SalesListItem
{
public virutal ICollection<SalesListWarehouseItem> WareHouseItems { get; set; }
}
public class SalesListWarehouseItem
{
public virtual SalesListItem Parent{ get; set; }
public virtual WarehouseItem WarehouseItem { get; set; }
public int Quantity { get; set; } // maybe double?
}
I'm trying to create a One-to-One relationship between two tables using a primary key and a unique key of the two tables (rather the primary keys).
The following is what I'd like to work.
// The principal end
public class A
{
// The primary Key
public int AId { get; set; }
// The navigation property
public virtual B B { get; set; }
}
// The dependent end
public class B
{
// The primary Key
public int BId { get; set; }
// The unique key
[Index(IsUnique = true)]
public int AId { get; set; }
// The navigation property
public virtual A A { get; set; }
}
But then I see this error:
Unable to determine the principal end of an association between the types 'A' and 'B'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
I'm quite sure a primarykey-uniquekey relationship is allowed in SQL Server. Looks like EF6 doesn't support it. EF Core 1.0 seems to, but it's not feasible to port to EF Core right now.
Why we need a need a relationship of this kind:
We have two tables A and B in production, but the one-to-one relationship, which should have been there is missing. The relationship is something we need so we can navigate from an A object to a B object with EF. Since both tables have values, we can't really make the primary key, the foreign key - we'll end up with incorrect data.
My approach to fixing this was to:
add a column
fill it with the correct A ids
make it unique
establish the 1-1 relationship
An alternate approach to fixing this is more than welcome.
This is possible with EF Core using Fluent API's .HasPrincipalKey() method. Unfortunately not supported in EF6 which is a shame as relationships over unique keys can essentially be treated the same as foreign key constrains so I'd imagine it would have been an easy addition.
Now that MS has forgot about EF6 and is focusing on EF Core, this will never happen. I really liked using the visual entity designers as it saved so much time. Looking at the thousand+ lines of code the EF Core DbContext scaffold generator spits out for me is discouraging to say the least. Sure, it's pretty when you're dealing with a demo project consisting of two cute tables but we all know this is never the case in the real world. The whole point of using an ORM is to save time but I'm not sure if having to manage thousands of lines of configuration code is any better. Just by two cents.
I'm banging my head on the keyboard with this one, basically what I'm trying to do is rather simple.
I reversed engineered an existing database with the EF Power Tools, I did that mostly because the database in question is quite old and missing a lot of foreign keys, or even primary key for that matter. The goal was to be able to add navigation properties to the generated model, mostly to have a cleaner code when querying the model.
Now I have 2 classes User and CostCentre, mapped to their respective tables Users and CostCentres with proper primary keys, PK of Users is Username named Userid in CostCentres, theoretical relation between those two is 1 to M (one User can have multiple CostCentre).
I added a navigation property to User like so
public virtual ICollection<CostCentre> CostCentres { get; set; }
I'm initializing the list in the default constructor with a simple
public User()
{
CostCentres = new List<CostCentre>();
}
To CostCentre I added a User property like so
public virtual User User { get; set; }
In the generated CostCentreMap class, I mapped the navigation property like so
this.HasRequired(cc => cc.User)
.WithMany(u => u.CostCentres)
.HasForeignKey(cc => cc.Userid);
Now whenever I query db.Users I can't get the property to fill, I know the navigation property kind of work, because when I do
db.Users
.Include(u => u.CostCentres);
The resulting query does the join properly on the proper columns in each table, however if I do
User user = db.Users
.Include("CostCentres")
.SingleOrDefault(u => u.Username == userName);
The property CostCentres stays empty.
I'm pretty sure I'm missing something quite obvious but for the love of Barnaby Jones, I can't get my hands on what.
Any help would be greatly appreciated.