Prevent Duplicates From Being Saved In Database - c#

I have produced an console application which saves data using Entity Framework , I have a table which is designed like this:
ID People_ID People_Address People_Postcode
--- ---------- -------------- ----------------
1 2 76 Nation Road B27 8NT
2 7 88 Grimestone Road B45 9WG
3 12 45 Wallock Road B22 4UI
To ensure duplicates are not be stored within the table the following code has been written:
ppl.People_Address = Address;
ppl.People_Postcode = Postcode;
ppl.People_ID = usr.ID;
If(db.tbl_people.Any(x=> x.people_address != ppl.People_Address) && (db.tbl_people.Any(x=> x.people_postcode != ppl.People_Postcode) && (db.tbl_people.Any(x=> x.People_ID != ppl.People_ID) {
db.tbl_people.Add(ppl)
db.SaveChanges();
}
However nothing is being added regardless if nothing exists in the table to compare to , any help??

You will need to check for each of your fields if they are null. For example:
x.people_address != ppl.People_Address || x.people_adress == null

The problem is the condition
if (db.tbl_people.Any(x=> x.people_address != ppl.People_Address)
&& (db.tbl_people.Any(x=> x.people_postcode != ppl.People_Postcode)
&& (db.tbl_people.Any(x=> x.People_ID != ppl.People_ID)
it should really be
if (!db.tbl_People.Any(x => x.people_address == ppl.People_Address
&& x.people_postcode == ppl.People_Postcode
&& x.People_ID == ppl.People_ID))
{
// No duplicate
}

There are few problems with this code.
First, you should not cause the database many times per calling "db.tbl_people" property getter. Do it one time and don't retrieve whole db collection.
Second, for the empty database
db.tbl_people.Any(x=> x.people_address != ppl.People_Address)
returns false because there is no entities in the tbl_people collection.
And the third your condition is not really check duplicates in the database.
Your query can be looks like code below:
// if there is no entities with same properties
if(db.tbl_people.Count(p => p.people_address == ppl.People_Address
&& p.people_postcode == ppl.People_postcode
&& p.People_ID == ppl.People_ID) == 0)
{
// then save new entity
db.tbl_people.Add(ppl)
db.SaveChanges();
}
This code will generate query to the database which will return just scalar variable and it'll be better to performance and communication channel.

Related

Complex if statement never gets executed

I have this long if statement that is checking for multiple things. It never seems to execute the code in the curly brackets though.
It is checking two objects.
"currentEngineObject" is the object as it exists in the database.
"engineList" is the object that is passed into this method.
So I am trying to check to make sure that the SizeId is not empty and also has a value for both objects.
If they both have values, but they are not the same value, I want to set the "SizeId" of engineList to the "SizeId" value that is in "currentEngineObject".
But even with test data, it never gets through the large if statement I have.
So I am wondering if there is a problem with my logic? Like should I be using "Or" instead of "And"?
Here is my if block:
if ((currentEngineObject.SizeId.HasValue && currentEngineObject.SizeId.Value != Guid.Empty)
&& (engineList.SizeId.HasValue && engineList.SizeId.Value != Guid.Empty)
&& (currentEngineObject.SizeId.Value != engineList.SizeId.Value))
{
engineList.SizeId = currentEngineObject.SizeId.Value;
}
Thanks!
Try this:
if ((currentEngineObject.SizeId.HasValue && currentEngineObject.SizeId.Value != Guid.Empty)
&& (engineList.SizeId.HasValue && engineList.SizeId.Value != Guid.Empty)
&& !currentEngineObject.SizeId.Equals( engineList.SizeId)) ////Use equals
{
engineList.SizeId = currentEngineObject.SizeId;
}

Get first value from table with where either have the value match or null with LINQ

I have a table from which I want a value like this.
I need price info w.r.t. states and vendor, for example, I want to calculate the price for a state, my table has data like either vendor has a price or default price.
So if I look for VendorA in NY I should get 2000. And if I look for VendorA in LA it will give me 1500.
I can get this by
public long GetPrice(string State, string Vendor){
var value = this.context.table.FirstOrDefault(a=>a.vendor == Vendor && a.state == State);
if(value == null){
value = this.context.table.FirstOrDefault(a=>a.vendor == null && a.state == State)?.Price;
}
}
GetPrice("NY","VendorA"); //This should give me 2000.
GetPrice("LA","VendorA"); // This should give me 1500
Please suggest is there is some more optimized way, means Can I get in a single DB call.
You could do it in one query by using:
private static long? GetPrice(string state, string vendor)
{
return table
.Where(x => x.State == state)
.OrderByDescending(x => x.Vendor)
.FirstOrDefault(x => x.State == state)
?.Price;
}
Filter out all prices in the matching state, order by vendor descending (to make null values appear last), and pick the first or default item matching the state from it.
var value = this.context.table.FirstOrDefault(a=>(a.vendor == "VendorA" || a.vendor == null) && a.state == "LA");
Try to use Find method:
var value = this.context.table.Find(a=>a.vendor == "VendorA" && a.state == "LA");
Please, see this performance considerations Find() vs. Where().FirstOrDefault()
UPDATE:
One call to database:
var values = this.context.table
.Where(a=>a.vendor == Vendor && a.state == State || a.vendor == null
&& a.state == State).ToList();

C# IQueryable not working

I have a findAll function that gets all the records from a Contacts table in the Database and then filters them depending on which values the user selected in the search form. The results are filtered one filter at the time.
IQueryable<Contact> resultContacts = db.Contacts;
if(request['Name'] != "")
{
resultContacts = resultContacts.Where(a => a.Name.Contains(Name));
}
if(request['Phone'] != "")
{
resultContacts = resultContacts.Where(a => a.Phone.Equals(Phone));
}
if(request['Company'] != "")
{
resultContacts = resultContacts.Where(a => a.Company.Contains(Company));
}
return resultContacts;
The problem is that now this is not working. The resultContacts.Where inside each if is resetting to the original resultContacts I had on the first line for some reason. For instance: when I debug, the changes apply inside the 1st if (I end up with 10 out of 100 records), but when I go into the 2nd if, the code is querying the original resultContacts, not the 10 I had as a result of the first if.
This worked fine for over a year until 2 weeks ago. I don't know if something changed on my code... if I added a reference or something that make this change.
Any idea why?
Thank you!
var results = db.Contacts
.Where(a => request["Company"] == String.Empty || a.Company.Contains(Company))
.And(a => request["Phone"] == String.Empty || a.Phone.Equals(Phone))
.And(a => request["Name"] == String.Empty || a.Name.Contains(Name)));

comparing 2 lists of objects and return changes in the new list

I have a web app that gives users a feature to update (no delete or add) multiple records on the same page. As users submit changes, I pull the original list from the database and use linq to compare it to the updated list. Any changed records will be put on a new list and send to database for update.
Below is my code to compare. As I debug, I can see the 2 lists are different but the code returns the Differences with comparer = null, first = null, second = null. Can you guys spot the bug?
var Differences = OriginalList.Where(x => !NewList.Any(x1 => x1.ServiceName == x.ServiceName
&& x1.ServiceDescription == x.ServiceDescription
&& x1.ServiceURL == x.ServiceURL
&& x1.OrderIndex == x.OrderIndex
&& x1.GroupID == x.GroupID
&& x1.Active == x.Active))
.Union(NewList.Where(x => !OriginalList.Any(x1 => x1.ServiceName == x.ServiceName
&& x1.ServiceDescription == x.ServiceDescription
&& x1.ServiceURL == x.ServiceURL
&& x1.OrderIndex == x.OrderIndex
&& x1.GroupID == x.GroupID
&& x1.Active == x.Active)));
return Differences;
You are probably looking for Linq's Except method.
https://msdn.microsoft.com/library/bb300779(v=vs.100).aspx
You'll need to define how to compare for equality of your "x1" object. Probably the easiest way to do that is to override Equals():
https://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
Then to get the difference, you simply do:
var Differences = OriginalList.Except(NewList);

An entity with the same identity already exists in this EntitySet. - WCF RIA Services

I have the following code that I would expect would check to see if an entity exists and, if not, add it to the collection. I then call submit changes on the context to save the changes.
int kwID = (int)(from d in this._keywordSource.Source where d.keyword.ToLower() == searchText.ToLower() select d.keywordID).FirstOrDefault();
if ( null == this._context.Rules.Where(e => e.keywordID == kwID && e.searchTerm == item.SearchTerm).FirstOrDefault())
{
this._context.Rules.Add(new Rule() { keywordID = kwID, searchTerm = item.SearchTerm, processed = false });
}
I am testing this with 3 keywords/searchTerm combos:
Apple/Apple
iPad/iPad
iPod/iPod
The first attempt never runs the .Add line of code. The second does, successfully. The third throws the error An entity with the same identity already exists in this EntitySet..
I've read that this has something to do with the identity & seed, especially if your seed is 0 in the db. Mine isn't (set to 1). The EntitySet itself has ~1900 items in it.
What am I missing here?
[EDIT]
Added the kwID code to show that keyword is ultimately the kwID in the conditional.
The primaryKey of this table is ruleID. This is what I believe is being violated in the error message.... but I don't know how or why.
IMHO, wrong condition.
Example:
U've got in your DataBase:
KWid: 5, SearchTerm: iPod
KWid: 6, SearchTerm: iPad
And in your condition u put values
KWid: 5, SearchTearm: GooglePhone
this._context.Rules.Where(e => e.keywordID == 5 && e.searchTerm == "GooglePhone").FirstOrDefault() returns null and so u try to add a row with existing KWid.
Solution: Change && condition to ||
if ( null == this._context.Rules.Where(e => e.keywordID == kwID || e.searchTerm == item.SearchTerm).FirstOrDefault())

Categories

Resources