One to many relations in linq-to-sql - sql-server

I'm writing a small application using ASP.NET MVC just for fun of it, but I have problem grasping how to design one particular variant of one to many relations. Since I'm using LinqToSQL I guess it's more about designing the tables than my C# code, but I'm mentioning it in case the way the data is to be used might affect the design.
The thing I'm having problem with is this:
Let's say I want to make a book database and let's say each book can have multiple names assigned to it (for example translations of the title). One of the titles needs to be the main one.
What seems to be the obvious solution for me, would be to make a table for books and another table for the names. Names get a BookId column and books get a MainNameId column and on top of that foreign keys are set, so when the models are generated in my application, the relations are set correctly off the bat.
However my logic fails as I won't be able to add a book without having a title first and I won't be able to add a title without having related book in the database first. Adding a book to the database was suppose to also add the first (and main title).
Anyway, I can think of a few workarounds for this problem, but I was wondering what's the proper way to solve this.

you have to save both records to 2 tables at the same time.
EntityFramework can do it for you in 1 save changes or you may add first a record to the book table and then to the names table and do "Save changes" for both of them at the same time.
this code should do it:
public class Book
{
public string BookId { get; set; }
public string ISBN { get; set; }
public IEnumerable<BookNames> Names { get; set; }
}
public class BookNames
{
public string BookId { get; set; }
public string BookName { get; set; }
public string Language { get; set; }
}
public class Functions
{
void createBook()
{
Book new_book=new Book();
new_book.ISBN = "RandomISBN";
new_book.Names = new IEnumerable<BookNames>() {
new BookNames{BookName = "The Good Book", Language = "ENG"},
new BookNames{BookName = "El buen libro", Language = "SPN"}
};
dbcontext db = new dbcontext();
db.Books.Add(new_book);
db.SaveChanges();
}
}

Related

Why am I getting DbUpdateException: OptimisticConcurrencyException?

I have a Category class:
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
I also have a Subcategory class:
public class Subcategory
{
public int SubcategoryId { get; set; }
public Category Category { get; set; }
public string SubcategoryName { get; set; }
}
And a Flavor class:
public class Flavor
{
public int FlavorId { get; set; }
public Subcategory Subcategory { get; set; }
public string FlavorName { get; set; }
}
Then I also have Filling and Frosting classes just like the Flavor class that also have Category and Subcategory navigation properties.
I have a Product class that has a Flavor navigation property.
An OrderItem class represents each row in an order:
public class OrderItem
{
public int OrderItemId { get; set; }
public string OrderNo { get; set; }
public Product Product { get; set; }
public Frosting Frosting { get; set; }
public Filling Filling { get; set; }
public int Quantity { get; set; }
}
I'm having issues when trying to save an OrderItem object. I keep getting DbUpdateException: An error occurred while saving entities that do not expose foreign key properties for their relationships. with the Inner Exception being OptimisticConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. I've stepped through my code several times and I can't find anything that modifies or deletes any entities loaded from the database. I've been able to save the OrderItem, but it creates duplicate entries of Product, Flavor, Subcategory and Category items in the DB. I changed the EntityState of the OrderItem to Modified, but that throws the above exception. I thought it might have been the fact that I have Product, Frosting and Filling objects all referencing the same Subcategory and Category objects, so I tried Detaching Frosting and Filling, saving, attaching, changing OrderItem entity state to Modified and saving again, but that also throws the above exception.
The following statement creates duplicates in the database:
db.OrderItems.Add(orderItem);
Adding any of the following statements after the above line all cause db.SaveChanges(); to throw the mentioned exception (both Modified and Detached states):
db.Entry(item).State = EntityState.Modified;
db.Entry(item.Product.Flavor.Subcategory.Category).State = EntityState.Modified;
db.Entry(item.Product.Flavor.Subcategory).State = EntityState.Modified;
db.Entry(item.Product.Flavor).State = EntityState.Modified;
db.Entry(item.Product).State = EntityState.Modified;
Can someone please give me some insight? Are my classes badly designed?
The first thing to check would be how the entity relationships are mapped. Generally the navigation properties should be marked as virtual to ensure EF can proxy them. One other optimization is that if the entities reference SubCategory then since SubCats reference a Category, those entities do not need both. You would only need both if sub categories are optional. Having both won't necessarily cause issues, but it can lead to scenarios where a Frosting's Category does not match the category of the Frosting's SubCategory. (Seen more than enough bugs like this depending on whether the code went frosting.CategoryId vs. frosting.SubCategory.CategoryId) Your Flavor definition seemed to only use SubCategory which is good, just something to be cautious of.
The error detail seems to point at EF knowing about the entities but not being told about their relationships. You'll want to ensure that you have mapping details to tell EF about how Frosting and SubCategory are related. EF can deduce some of these automatically but my preference is always to be explicit. (I hate surprises!)
public class FrostingConfiguration : EntityTypeConfiguration<Frosting>
{
public FlavorConfiguration()
{
ToTable("Flavors");
HasKey(x => x.FlavorId)
.Property(x => x.FlavorId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasRequired(x => x.SubCategory)
.WithMany()
.Map(x => x.MapKey("SubCategoryId");
}
}
Given your Flavor entity didn't appear to have a property for the SubCategoryId, it helps to tell EF about it. EF may be able to deduce this, but with IDs and the automatic naming conventions it looks for, I don't bother trying to remember what works automagically.
Now if this is EF Core, you can replace the .Map() statement with:
.ForeignKey("SubCategoryId");
which will set up a shadow property for the FK.
If SubCats are optional, then replace HasRequired with HasOptional. The WithMany() just denotes that while a Flavor references a sub category, SubCategory does not maintain a list of flavours.
The next point of caution is passing entities outside of the scope of the DBContext that they were loaded. While EF does support detaching entities from one context and reattaching them to another, I would argue that this practice is almost always far more trouble than it is worth. Mapping entities to POCO ViewModels/DTOs, then loading them on demand again when performing updates is simpler, and less error-prone then attempting to reattach them. Data state may have changed between the time they were initially loaded and when you go to re-attach them, so fail-safe code needs to handle that scenario anyways. It also saves the hassle of messing around with modified state in the entity sets. While it may seem efficient to not load the entities a second time, by adopting view models you can optimize reads far more efficiently by only pulling back and transporting the meaningful data rather than entire entity graphs. (Systems generally read far more than they update) Even for update-heavy operations you can utilize bounded contexts to represent large tables as smaller, simple entities to load and update a few key fields more efficiently.

How do I use a composite key for a one to many relationship in Code First EF

I am using EF Code First.
I need two tables, LedgerCategories and LedgerSubCategories with a one-to-many relationship (Categories -> SubCategories), with the keys in each being codes (strings) - i.e. LedgerCategoryCode and LedgerSubCategoryCode respectively. However, I need to allow the SubCategoryCode values to be the same for different Categories.
E.g. CategoryCode = REHAB, SubCategoryCodes = MATL, CONTR, and FEES; and CategoryCode = MAINT, SubCategoryCodes = MATL, CONTR, and FEES.
I'm thinking I need to use a composite key and include both the CategoryCode and SubCategoryCode fields in the LedgerSubCategories table. Currently I have:
public class LedgerCategory
{
[Key]
public string LedgerCategoryCode { get; set; }
public string Description { get; set; }
public List<LedgerSubCategory> LedgerSubCategories { get; set; }
}
public class LedgerSubCategory
{
[Key, Column(Order = 0)]
public string LedgerCategoryCode { get; set; }
[Key, Column(Order = 1)]
public string LedgerSubCategoryCode { get; set; }
public string Description { get; set; }
}
I am seeding these tables using only instances of the LedgerCategory class, having each contain a List of appropriately instantiated LedgerSubCategory classes. This appears to both set up the DB schema correctly (in my perception), and populate both tables appropriately.
But, when I reinstantiate a simple List of LedgerCategory, i.e.
using (var db = new BusinessLedgerDBContext())
{
var LedgerCategories = db.LedgerCategories.ToList();
}
The LedgerCategory instances don't contain their respective List of associated LedgerSubCategory instances.
I am trying to avoid, what seems like a kludge, to introduce a unique number or Guid ID field in LedgerSubCategories as a PK and just index off the other Code fields. I haven't tried this, but I'm not sure it would cause any different results for reinstantiating the LedgerCategories and getting associated LedgerSubCategories.
Any advice on how to do this appropriately and get proper results is appreciated.
To, I suppose, answer my own question, I have found that overriding OnModelCreating() in the respective DbContext with Fluent API to establish the one to many relationship and foreign key when the Code First framework establishes the desired DB Schema. There appears no other way to do this, such as with Attributes. By many accounts of others, including MSDN, Fluent API appears to be what is needed. However, that has led me to a new issue, or set of issues, which I've posed as a question here.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configures the one-many relationship between Categories and
// SubCategories, and established the Foreign Key in SubCategories
modelBuilder.Entity<Category>()
.HasMany<SubCategory>(c => c.SubCategories)
.WithRequired(s => s.Category)
.HasForeignKey<string>(s => s.CategoryCode);
}

dreaded "Ids can not be autogenerated for entities with multipart keys"

Ok I’m at a loss, being new to breeze I’m still learning the ropes. My project uses the hot towel template for AngularJs and breeze from John Papa.
He's what I’m trying to achieve: I have a master\slave tables in my database. An "Agency" has many people it can "Notify". Here are the EF classes for the server side:
public class Agency {
public Agency() {
this.Notifies = new HashSet<Notify>();
}
public long Id { get; set; }
[Required, MaxLength(50)]
public string Name { get; set; }
<<removed unneeded details>>
public bool Active { get; set; }
public virtual ICollection<Notify> Notifies { get; set; }
}
public class Notify
{
public long Id { get; set; }
public long? AgencyId { get; set; }
public string Name { get; set; }
<<removed unneeded details>>
public virtual Agency Agency { get; set; }
}
Now the Maps:
public class AgencyMaps : EntityTypeConfiguration<Agency>
{
internal AgencyMaps()
{
HasKey(x => x.Id);
}
}
public class NotifyMap : EntityTypeConfiguration<Notify>
{
internal NotifyMap()
{
HasKey(x => x.Id);
HasOptional(x => x.Agency)
.WithMany(p => p.Notifies)
.HasForeignKey(i => i.AgencyId);
}
}
Now on the client side I use breeze to create new entities like this:
// create a new entity
function create() {
return manager.createEntity(entityName);
}
// create a new notify entity
function createNotify(){
return manager.createEntity(entityNameNotify);
}
Then there are two scenarios I need to achieve:
- First is where I retrieve an existing agency and add additional
people to notify
- Second is where I create a new agency and add people
to notify
Both fail in the same place.
Note: I’m using SQL server and my Id fields are bigint (long) at this point in time.
I’m retrieving the “Agency” entity and placing it in a variable called “vm.agency”. “vm.agency” has a navigation called “notifies” with an entity type of “Notify”. So when I want to create and add a new person I’m calling this function:
function addNotifyRec(){
if (vm.agency !== undefined){
var notifyRec = datacontext.agency.createNotify(); //<<< fails here
notifyRec.agencyId = vm.agency.id;
notifyRec.name = vm.notify.name;
<<removed unneeded details>>
vm.agency.notifies.push(notifyRec);
logSuccess(“New person to notify added”);
}
else
{ logError(“Agency is undefined”); }
}
As soon as the createNotify() is called I get the “Ids can not be autogenerated for entities with multipart keys” error.
So I’m stuck. It seems to me this is a pretty common scenario. I am obviously not understanding the breeze framework well enough to implement this. If you can point me in the right directions I’d appreciate your help.
UPDATE 4/9/2014
I'm thinking i could eliminate this issue altogether if i switch over to guid id and generate them client side. Is this correct thinking?
What's interesting here is that Breeze thinks that Notify.Id and Notify.AgencyId are multi part primary keys but they are actually not. Id is a PK and AgencyId is an FK. The only thing that I can think of is try removing the EntityTypeConfiguration for both Agency and Notify, specifically the part where it specifies HasKey and HasForeignKey. This Fluent API configuration shouldn't be required as EF will match your configuration by convention instead.
I took a different approach on working around my issue. Since i have the luxury to change out the id types, i swapped out the bigint ids to Uuid types and removed the auto generation of the ids in sql. Now i'm just creating my own ids using breeze.core.getUuid() when a new record is created. Not sure this is the most efficient way to work around the issue, but it seems to be working fine.

SQLite - what and how to?

I'm all new to databases and I've heard that SQLite should be straight forward, but I kinda find that not to be the case.
I have a decent knowledge of C# and WPF and I'm trying to make a small personal project which I want to use in daily life. My idea is a program that manages receipts that I bring home.
I have two Models - Item and Receipt
class Item
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int ReceiptId { get; set; }
}
class Receipt
{
public int Id { get; set; }
public string Store { get; set; }
public double Price { get; set; }
public DateTime Date { get; set; }
}
My corrent problem is that I've been caught in all the different SQLite "versions" available. I've found that there is ADO.NET and LINQ and some other sorts.. what does these different ones mean and is the programming syntax for each of them different and which would be most suitable for my case?
I'm developing in Visual Studio 2012 and I've managed to download the NuGet SQLite package that goes by the name "System.Data.SQLite (x86/x64)".
I want to create a database, create two tables with these object in them, but I have basicly no idea how to and searching google for a day or two has just me that more confused, since so many people use different syntaxes and most of the tutorials I've find relate to how people used the old "SQLite.dll". So what my question is, is how do I make a database that fits this program structure and how do I write, read, connect and disconnect to my database.

Coming from a relational database background, how should I model relationships in db4o (or any object database)?

I'm experimenting with db4o as a data store, so to get to grips with it I thought I'd build myself a simple issue tracking web application (in ASP.NET MVC). I've found db4o to be excellent in terms of rapid development, especially for small apps like this, and it also negates the need for an ORM.
However, having come from a SQL Server/MySQL background I'm a little unsure of how I should be structuring my objects when it comes to relationships (or perhaps I just don't properly understand the way object databases work).
Here's my simple example: I have just two model classes, Issue and Person.
public class Issue
{
public string ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime? SubmittedOn { get; set; }
public DateTime? ResolvedOn { get; set; }
public Person AssignedBy { get; set; }
public Person AssignedTo { get; set; }
}
public class Person
{
public string ID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
The ID properties are just GUID strings generated by the .NET Guid.NewGuid() helper.
So here's how I initially thought the application would work; please ignore any security concerns etc and assume we already have a few Person objects stored in the database:
User logs in. Query the database for the Person which matches the username and password, and store his/her GUID id as a session variable. Redirect to app home screen.
Logged in user creates a new issue ticket, selecting the user to assign it to from a drop-down list. They fill in the other details (Title, Description etc), and then submit the form.
Query the Person objects in the database (by their GUID ID's) to get an object representing the logged in user and one representing the user the ticket has been assigned to. Create a new Person object (populated with the posted form data), assign the Person objects to the Issue object's AssignedBy and AssignedTo properties, and store it.
This would mean I have two Person objects stored against each Issue record. But what happens if I update the original Person—do all the stored references to that Person in the various issue objects update, or do I have to handle that manually? Are they references, or copies?
Would it be better/more efficient to just store a GUID string for the AssignedBy and AssignedTo fields (as below) and then look up the original person based on that each time?
public class Issue
{
public string ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime? SubmittedOn { get; set; }
public DateTime? ResolvedOn { get; set; }
public string AssignedByID { get; set; }
public string AssignedToID { get; set; }
}
I think I'm just stuck in a certain way of thinking which is confusing me. If someone could explain it clearly that would be most helpful!
Object-Databases try to provide the same semantics as objects in memory. The rule of thumb is: It works like objects in memory. Object databases store references between the objects in the database. When you update the object, that object is updates. And if you have a reference to that objects, you see the changed version.
In your case, the Issue-objects refer to the person object. When you update that person, all Issues which refer to it 'see' that update.
Of course, primitive types like int, strings, longs etc are handled like value objects and not a reference objects. Also arrays are handled like value objects in db4o, this means a array is stored together with the object and not as a reference. Everything else is stored as a reference, even collections like List or Dictionaries.
Please take a look at:
http://developer.db4o.com/Documentation/Reference/db4o-7.4/java/reference/html/reference/basic_concepts/database_models/object-relational_how_to.html
Best!

Resources