Entity Framework 4.1: Possible to save a single table out of a data context containing multiple tables? - asp.net-mvc-3

I have a chicken and egg problem, it's trivial, so I thought I would ask what's the normal pattern to save an aggregate root where all the primary keys are identity fields.
I have a typical contact entity:
Customer {
HomeAddress {
}
WorkAddress {
}
}
where both addresses are stored in the address table and the only primary key is the identity field. We check all fields against each other to keep unique address records.
Here's the problem:
I need to retrieve the Address identity field to hookup the foreign keys, so I save the Address record prior to saving the Customer record only if it's unique, otherwise I load that existing Address.
If Address is in the same DC as Customer, then customer saves too prematurely (not all records are set.)
If Address is in a separate DC, then it doesn't hookup to the Customer record that has it's own DC because you cannot have an entity associated with two DCs (can't open in one, then save in another.)
So my thinking is that I would need a separate repository for every Address, then separately load the address again in the other DC, making redundant calls to the database for the same information.
Is there a way to partially save records in a data context / container in Entity Framework 4.1? For example, to save Address by itself while still being in the same DC?

The answer to your bold question is "No" as far as I can tell. The context is a unit of work and SaveChanges commits every new, changed or deleted object to the database in a single transaction. You cannot selectively say: Save only this or that object or save only entities in state Added and don't commit entities in state Modified or Deleted or something.
As a workaround you could try that:
using (var context1 = new MyContext())
{
Address address = context1.Addresses.Where(predicate).FirstOrDefault();
// if address != null it is attached now to context1
if (address == null)
{
// ... otherwise create new address in another context and save
using (var context2 = new MyContext())
{
address = new Address { Name = name, ... }
context2.Addresses.Add(address);
context2.SaveChanges();
} // context2 destroyed now and address is not attached to it anymore
// ... and attach to context1
context1.Addresses.Attach(address);
}
customer.HomeAddress = address;
// ...
context1.SaveChanges();
}
This way address is never attached to the two contexts at the same time. I am not sure though if this works.
Edit
I must add (because my code above looks so weird) that "normally" you could do all this in context1 alone. But I understood your point 2 this way that there is something happening in // ... (which I don't understand) before SaveChanges which prevents you to save the new address and the customer at the same time.

Related

Using "Any" or "Contains" when context not saved yet

Why isn't the exception triggered? Linq's "Any()" is not considering the new entries?
MyContext db = new MyContext();
foreach (string email in {"asdf#gmail.com", "asdf#gmail.com"})
{
Person person = new Person();
person.Email = email;
if (db.Persons.Any(p => p.Email.Equals(email))
{
throw new Exception("Email already used!");
}
db.Persons.Add(person);
}
db.SaveChanges()
Shouldn't the exception be triggered on the second iteration?
The previous code is adapted for the question, but the real scenario is the following:
I receive an excel of persons and I iterate over it adding every row as a person to db.Persons, checking their emails aren't already used in the db. The problem is when there are repeated emails in the worksheet itself (two rows with the same email)
Yes - queries (by design) are only computed against the data source. If you want to query in-memory items you can also query the Local store:
if (db.Persons.Any(p => p.Email.Equals(email) ||
db.Persons.Local.Any(p => p.Email.Equals(email) )
However - since YOU are in control of what's added to the store wouldn't it make sense to check for duplicates in your code instead of in EF? Or is this just a contrived example?
Also, throwing an exception for an already existing item seems like a poor design as well - exceptions can be expensive, and if the client does not know to catch them (and in this case compare the message of the exception) they can cause the entire program to terminate unexpectedly.
A call to db.Persons will always trigger a database query, but those new Persons are not yet persisted to the database.
I imagine if you look at the data in debug, you'll see that the new person isn't there on the second iteration. If you were to set MyContext db = new MyContext() again, it would be, but you wouldn't do that in a real situation.
What is the actual use case you need to solve? This example doesn't seem like it would happen in a real situation.
If you're comparing against the db, your code should work. If you need to prevent dups being entered, it should happen elsewhere - on the client or checking the C# collection before you start writing it to the db.

How to load multiple related entities in DbUpdateConcurrencyException

I have 3 related tables
Person entity: with two Foreign keys from Address entity (Address and Address1) and one foreign key from Owners table
Address Entity has one foreign key from Owners table
The person view has fields from Address entity and while tracking the concurrency check
var entry = ex.Entries.Single();
var databaseValues = (Person)entry.GetDatabaseValues().ToObject();
var clientValues = (Person)entry.Entity;
works fine for Person fields.
However when I try to access
databasevalues.Address.City or databasevalues.Address1.City it gives a null exception. This I think is due to Address Entity not loaded in the begining
Request for suggestions
You might try explicitly loading the related entities in your query:
IQueryable<Person> persons = DataContext.Persons.Where(p => p.City == "Hoboken").Include("Address")
would explicitly load related address entries for the person instances returned.
Another option is to disable the Lazy Loading option in your edmx file; open the file, then the properties panel, set Lazy Loading = false.

How to prevent multiple users from adding an item to a Sharepoint list simultaneously

I am using a simple form to allow people to sign up for an event. Their details are saved to a Sharepoint list. I have a quota of people who can sign up for an event (say 100 people).
How can I prevent the 100th and the 101st person from signing up concurrently, causing the quota check to allow the 101st person to sign up (because the 100th person isn't in the list yet)?
Place the ItemAdding code inside a lock statement to make sure that only one thread at a time can enter the critical section of code:
private Object _lock = new Object();
public override void ItemAdding(SPItemEventProperties properties)
{
lock(_lock)
{
// check number of the list items and cancel the event if necessary
}
}
I came up with this idea of a solution for a farm with multiple WFEs - a shared resource (a row in a table in pseudo-code above) gets locked during the time the item is added to the list:
private Object _lock = new Object();
public override void ItemAdding(SPItemEventProperties properties)
{
try
{
// 1. begin a SQL Server transaction
// 2. UPDATE dbo.SEMAPHORE
// SET STATUS = 'Busy'
// WHERE PROCESS = 'EventSignup'
lock(_lock)
{
// 3. check number of the list items and cancel the event if necessary
}
}
finally
{
// 4. UPDATE dbo.SEMAPHORE
// SET STATUS = ''
// WHERE PROCESS = 'EventSignup'
// 5. commit a SQL Server transaction
}
}
I left the lock statement because I'm not sure what will happen if the same front-end server tries to add the item #100 and #101 - will the transaction lock the row or will it not because the same connection to SQL Server will be used?
So then you can use event receivers item adding method. at item adding, your item is not created, you can calculate the current count of signed up people. if it is bigger then 100 you can cancel item adding.
but sure, more than one item adding method can be fired, to prevent that you can calculate the current count of people and increase the count +1, and keep that value somewhere else (on a field on event item perhaps) and all item adding methods can check that value before adding the item.
item added method is too late for these operations.
this would be the solution i would use.
I guess if you are updating a column, lets say - "SignUp Count", then one of the users will get the Save Conflict issue. Whoever updated the value for the first time wins and the second one will fail.
Regards,
Nitin Rastogi

Handling parameters from dynamic form for one-to-many relationships in grails

My main question here is dealing with the pramas map when having a one-to-many relationship managed within one dynamic form, as well as best practices for dealing with one-to-many when editing/updating a domain object through the dynamic form. The inputs for my questions are as follows.
I have managed to hack away a form that allows me to create the domain objects shown below in one Dynamic form, since there is no point in having a separate form for creating phone numbers and then assigning them to a contact, it makes sense to just create everything in one form in my application. I managed to implement something similar to what I have asked in my Previous Question (thanks for the people who helped out)
class Contact{
String firstName
String lastName
// ....
// some other properties
// ...
static hasMany = [phones:Phone]
static mapping = {
phones sort:"index", cascade: "all-delete-orphan"
}
}
class Phone{
int index
String number
String type
Contact contact
static belongsTo = [contact:Contact]
}
I basically managed to get the values from the 'params' map and parse them on my own and create the domain object and association manually. I.e. i did not use the same logic that is used in the default scaffolding, i.e.
Contact c = new Contact(params)
etc...., i just looped through all the params and hand crafted my domain objects and saved them and everything works out fine.
My controller has code blocks that look like this (this is stripped down, just to show a point)
//create the contact by handpicking params values
def cntct = new Contact()
cntct.firstName = params.firstName
cntct.lastName = params.lastName
//etc...
//get array of values for number,type
def numbers = params['phone.number']
def types = params['phone.type']
//loop through one of the arrays and create the phones
numbers.eachWithIndex(){ num, i ->
//create the phone domain object from
def phone = new Phone()
phone.number = num
phone.type = types[i]
phone.index = i
cntct.addToPhones(phone)
}
//save
My questions are as follows:
What is the best practice of handeling such a situation, would using Command objects work in this case, if yes where can i found more info about this, all the examples I have found during my search deal with one-to-one relationships, I couldn't find an example for one-to-many?
What is the best way to deal with the relatiohsips of the phones in this case, in terms of add/removing phones when editing the contact object. I mean the creation logic is simple since I have to always create new phones on save, but when dealing with updating a contact, the user might have removed a phone and/or editing an exiting one and/or added some new phones. Right now what I do is just delete all the phones a contact has and re-create them according to what was posted by the form, but I feel that's not the best way to do it, I also don't think looping over the existing ones and comparing with the posted values and doing a manual diff is the best way to do it either, is there a best practice on how to deal with this?
Thanks, hopefully the questions are clear.
[edit] Just for more information, phone information can be added and deleted dynamically using javascript (jquery) within the form [/edit]
disclaimer: i do not know if the following approach works when using grails. Let me know later.
See better way for dynamic forms. The author says:
To add LineItems I have some js that calculates the new index and adds that to the DOM. When deleting a LineItem i have to renumber all the indexes and it is what i would like to avoid
So what i do
I have a variable which stores the next index
var nextIndex = 0;
When the page is loaded, i perform a JavaScript function which calculates how many child The collection has and configure nextIndex variable. You can use JQuery or YUI, feel free.
Adding a child statically
I create a variable which store the template (Notice {index})
var child = "<div>"
+= "<div>"
+= "<label>Name</label>"
+= "<input type="text" name=\"childList[{index}].name\"/>"
+= "</div>"
+= "</div>"
When the user click on the Add child button, i replace {index} - by using regex - by the value stored in the nextIndex variable and increment by one. Then i add to the DOM
See also Add and Remove HTML elements dynamically with Javascript
Adding a child dinamically
Here you can see The Paolo Bergantino solution
By removing
But i think it is the issue grow up when deleting. No matter how many child you remove, does not touch on the nextIndex variable. See here
/**
* var nextIndex = 3;
*/
<input type="text" name="childList[0].name"/>
<input type="text" name="childList[1].name"/> // It will be removed
<input type="text" name="childList[2].name"/>
Suppose i remove childList1 What i do ??? Should i renumber all the indexes ???
On the server side i use AutoPopulatingList. Because childList1 has been removed, AutoPopulatingList handles it as null. So on the initialization i do
List<Child> childList = new AutoPopulatingList(new ElementFactory() {
public Object createElement(int index) throws ElementInstantiationException {
/**
* remove any null value added
*/
childList.removeAll(Collections.singletonList(null));
return new Child();
}
});
This way, my collection just contains two child (without any null value) and i do not need to renumber all the indexes on the client side
About adding/removing you can see this link where i show a scenario wich can gives you some insight.
See also Grails UI plugin
Thanks,
Your answer brought some insight for me to do a wider search and I actually found a great post that covers all the inputs in my question. This is just a reference for anyone reading this. I will write a blog entry on how I implemented my case soon, but this link should provide a good source of ino with a working exmaple.
http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/
Most of the time I use ajax to manage such problem.
So when the user clicks add new phone I get the template UI from the server for manageability purpose ( the UI just same GSP template that I use to edit, update the phone), so this way you are not mixing your UI with your js code, whenever you want to change the UI you have to deal only with our GSP code.
Then after getting the UI I add it to the page using jquery DOM manipulation. Then after filling the form when they hit add(save) the request is sent to the server via ajax and is persisted immediately.
When the user clicks edit phone the same UI template is loaded from the server filled with existing phone data, then clicking update will update the corresponding phone immediately via ajax, and same thing applies to delete operation.
But one day I got an additional scenario for the use case that says, "until I say save contact no phone shall be saved on the backend, also after adding phones to the contact on the ui if navigate away to another page and come back later to the contact page the phones I added before must be still there." ugh..
To do this I started using the Session, so the above operations I explained will act on the phone list object I stored on the session instead of the DB. This is simple perform all the operation on the phonesInSession but finally dont forget to do this(delete update):
phonesToBeDeleted = phonesInDB - phonesInSession
phonesToBeDeleted.each{
contact.removeFromPhones(it)
it.delete()
}
I know I dont have to put a lot of data in session but this is the only solution I got for my scenario.
If someone has got similar problem/solution please leave a comment.
First, in all your input fields names you add an #:
<input type="text" name="references[#].name"/>
Second, add call a function before submitting:
<g:form action="save" onsubmit="replaceAllWildCardsWithConsecutiveNumbers();">
Third, this is the code for the function that you call before submitting the form:
function replaceAllWildCardsWithConsecutiveNumbers(){
var inputs = $('form').find("[name*='#']");
var names = $.map(inputs, function(el) { return el.name });
var uniqueNames = unique(names);
for (index in uniqueNames) {
var uniqueName = uniqueNames[index];
replaceWildCardsWithConsecutiveNumbers("input", uniqueName);
replaceWildCardsWithConsecutiveNumbers("select", uniqueName);
}
}
function unique(array){
return array.filter(function(el, index, arr) {
return index === arr.indexOf(el);
});
}
function replaceWildCardsWithConsecutiveNumbers(inputName, name){
counter = 0;
$(inputName + "[name='" + name + "']").each(function (i, el) {
var curName = $(this).attr('name');
var newName = curName.replace("#", counter);
$(this).attr('name', newName);
counter += 1;
});
}
Basically, what the code for replaceAllWildCardsWithConsecutiveNumbers() does, is to create a list for all input (or select) elements whose name contains an #. Removes the duplicates. And then iterates over them replacing the # with a number.
This works great if you have a table and you are submitting the values to a command object's list when creating a domain class for the first time. If you are updating I guess you'll have to change the value of counter to something higher.
I hope this helps someone else since I was stuck on this issue for a while myself.

EntityRef<T> Issues, not returning value from Lookup List

Ok, I'll explain this as much as I can...
I've got a Site Lookup Column called EEE Content Type which refers to the Site Content Item Type Types List.
Now in my custom list (which inherits from Item), I am referencing that column, and it comes up in sharepoint fine and displays the lookup values.
The issue is when I'm using SPMetal.exe to generate the types it whinges about "Key isn't present in the dictionary" and fails. So I remove the definition of the column in the parameters.xml file for SPMetal, and re-generate the classes.
Now I've manually added the property and association.
private EntityRef<SiteContentItemTypeItem> _eeeContentType;
[Association(Name = "EEE_x0020_Content_x0020_Type", Storage = "_eeeContentType", MultivalueType = AssociationType.Single, List = "Site Content Item Types")]
public SiteContentItemTypeItem EEEContentType
{
get
{
return this._eeeContentType.GetEntity();
}
set
{
this._eeeContentType.SetEntity(value);
}
}
SiteContentItemTypeItem inherits from Item so its class is empty.
But when I load the custom list I have created, i get the first entry and the EEEContentType field is null...
using (IntranetDataContext context = new IntranetDataContext("http://siteurl")) {
context.ObjectTrackingEnabled = false;
EntityList<SiteContentItem> alerts = context.GetList<SiteContentItem>("User Alerts");
SiteContentItem alert = (from tmpalert in alerts where tmpalert.Id == 1 select tmpalert).First();
SiteContentItemTypeItem contentType = alert.EEEContentType;
}
I'm all out of ideas...
Should the List value in the Association attribute be that of a collection in the class or is it refering to the actual lookup list name?
Figured it out...
Stupid of me to "assume" when creating site lookup columns via code that SharePoint would use the proper naming conventions for FieldNames with spaces.
So the fieldName was correct, its InternalName wasn't the one I was expecting. And as sharepoint linq requires the internal names, it was throwing internal exceptions in the Linq.SharePoint DLL.

Resources