LinqPad conversion error - c#

i am getting an error on DuplicateOrder(TestOrder) as "cannot convert from tables.Order to int" even though the OrderID in the Orders table is an int
void DuplicateOrder(int orderId)
{
string methodName = MethodBase.GetCurrentMethod().Name;
try {
using (MSBLegacyContext db = new MSBLegacyContext())
{
var TestOrder = db.Orders.Where(i=>i.OrderID == orderId).FirstOrDefault();
DuplicateOrder(TestOrder);
}
}
catch (Exception ex)
{
Console.WriteLine(methodName, ex, string.Format("Test", orderId));
}}
what am i missing here?

Root cause, the FirstOrDefault in below line will return the either first order object or null.
var TestOrder = db.Orders.Where(i=>i.OrderID == orderId).FirstOrDefault();
So type of testOrder is order, but the below method call is expecting the int parameter.
DuplicateOrder(TestOrder);
That's the reason yor are getting -
cannot convert from tables.Order to int
To fix the issue, you need to add Select query in the Linq query and select the int column, something like below -
var TestOrder = db.Orders.Where(i=>i.OrderID == orderId).Select(s=> s.YourIntColumn).FirstOrDefault();
Edit:
After looking at you entire method and comments from others, you method call will definitely go to infinite loop. As you have not mentioned the purpose of this code, I am just assuming that you want to see whether a particular orderid is duplicate in the database or not. For that you can just use Count query and return the Boolean value. (not sure why do you have void in your method signature)
bool DuplicateOrder(int orderId) // changed from void to bool
{
using (MSBLegacyContext db = new MSBLegacyContext())
{
return db.Orders.Where(i=>i.OrderID == orderId).Count()>1; // returns true if more than 1 order found
}
}

If you have coded it correctly in your code, and if for a given orderId there were an Order, then your method would cause an infinite loop. Having said that, below is the correct way to get the int OrderId value:
using (MSBLegacyContext db = new MSBLegacyContext())
{
var TestOrder = db.Orders
.FirstOrDefault(i=>i.OrderID == orderId);
if (TestOrder != null)
{
var orderId = TestOrder.OrderId;
// ...
}
// else whatever you would do
}
If OrderId is a primary key, then you would use SingleOrDefault() instead of FirstOrDefault(). The difference is, if there is more than 1 entry in the database with given orderId, SingleOrDefault() would throw an error - and in the case of primary keys that is what you want.

Related

C#, SQL Server, Linq-to-SQL - cannot find item in query results (list of classes)

I am trying to make a list of class objects that I gather from a database. I am able to use a Linq-to-SQL class in order to use Linq to make a list of class objects.
I am able to look up things in the list however it fails when I look up something that is not in the list (null error exception). I would like to test for null or somehow figure out if my item is not in the list but
q.Find(x => (x.fid1 == "abc123")).fid1 = "9454a3" == null
generates a null error exception. This is my first time using the Linq-to-SQL class so any input as to how I am using it would be welcome as well.
class TestClass
{
public class FIDClass
{
public System.String fid1 { get; set; }
public System.String fid2 { get; set; }
public System.Int32 fid3 { get; set; }
}
static void Main()
{
// linq to SQL class
DataClasses1DataContext db = new DataClasses1DataContext();
var q = (from dbfile in db.GetTable<DataTable>()
where dbfilefid3 == 15
select new FIDClass
{
fid1 = dbfile.fid1,
fid2 = dbfile.fid2,
fid3 = (int) dbfile.fid3
}).ToList<FIDClass>();
// if it's found, the following works fine
// if it's not found, I get a null error exception on the if stmt
if (q.Find(x => (x.fid1 == "abc123")).fid1 == "abc123" )
{ MessageBox.Show("Found");
}
}
}
Any help, thoughts, feedback would be greatly appreciated
On my iPad, so can't test this out.
Depending on version of .net you could try null coalesce
if (q.Any(x => (x?.fid1 == "abc123")) )
Otherwise,
if (q.Any(x => x!=null && (x.fid1 == "abc123"))
You should check for null as below:
if (q.Find(x => x.fid1 == "abc123") != null )
{ MessageBox.Show("Found");
}
else
{ MessageBox.Show("NOT Found");
}
Please mark as answered if that solved your problem.
First of all it's 2017 don't use Linq to SQL it's been depreciated for a while now.
Second your query is not optimized at all. You are pulling all the data from the server with the ToList method that is bad what you want to use is IQueriables to do the query operations.
And the problem you are having is that the find method returns a null if no object is found so use the Any method if you just want to check if there is an object that satisfies the condition Any((x)=>x.fid1 == "abc123")

After checking if a record exist, and it doesn't, SaveChanges gives an DbUpdateException

I have a table that has a unique index on two columns, F1 and Kant[1]. There is no Foreign Keys just Primary Key (which is an integer Id) and this index.
Before I add a new record I do a check if a record with this index exists in the database.[2]
I get that it doesn't! ExistsLaserData returns false.
I then add the record to the DbSet and execute SaveChanges but now I get an exception
DbUpdateException: SqlException: Violation of UNIQUE KEY constraint
'IX_laserdata_F1_Kant'. Cannot insert duplicate key in object
'dbo.LaserData'. The duplicate key value is (123456, NULL).
This is the record I have added!
The context is initialized with
LaserDataContext context = new LaserDataContext();
OrderBy(x => x.F1).ThenBy(x => x.Kant).ToList();
The two methods that I'm using
public bool ExistsLaserData(string article, string kant)
{
bool result = false;
var found = _context.LaserData.Where(x => x.F1 == article && x.Kant == kant).FirstOrDefault();
if (found != null)
{
result = true;
}
return result;
}
public void AddLaserData(ref LaserData d)
{
try
{
_context.LaserData.Add(d);
_context.SaveChanges();
}
catch (Exception ex)
{
throw;
}
}
Why does the record not exist when I check for it or why does it exist when I do SaveChanges?
[1] The beginning of this database was an Excel document, thus the strange names...
[2] I don't want to skip the ExistLaserData check, so please don't suggest that I should just use the exception.
Here you are checking for both the values in the same row and it returns a row only if both the keys are the same for a single row.
Can you try this? Instead of && , use ||
public bool ExistsLaserData(string article, string kant)
{
bool result = false;
var found = _context.LaserData.Where(x => x.F1 == article || x.Kant == kant).FirstOrDefault();
if (found != null)
{
result = true;
}
return result;
}
I think you should cast the article to integer then check if that exists or not.
As you said F1 is int and article is string so you can not compare them.
Then you can use this for add or update :
LaserData found = _context.LaserData.FirstOrDefault( p => p.F1==(int) article);
if(found == null)
{
_context.LaserData.Add(d);
_context.SaveChanges();
}
I hope this helps you. maybe you need to explain more if this is not you want.
if the article type is like F1 so u can write without cast to int :
LaserData found = _context.LaserData.FirstOrDefault( p => p.F1== article);
You do not have to check kant if it is not unique. But you can check if u like.
Edit :
just use this :
public bool ExistsLaserData(string article, string kant)
{
bool result = false;
LaserData found = _context.LaserData.FirstOrDefault(x => x.F1 == article && x.Kant == kant);
if (found != null)
{
result = true;
}
return result;
}
More likely than not your kant property is not properly mapped. This would explain both the Exception and the behavior of the code.
The Exception states you tried to insert a null value for kant which would make sense because EF never sent over a value due to the incorrect mapping.
ExistsLaserData always returns false as long as you do not pass null into the method for the kant parameter. This would lead your code to always try the AddLaserData method.
So the fix is to ensure that this property is properly mapped and to correct column.
If that is not it then you are trying to insert multiple records with the same F1 value but with a null kant value which would break the unique index. The only way around that is to alter the index with a where filter so that it only checks when the kant has a value.
CREATE UNIQUE NONCLUSTERED INDEX [IX_laserdata_F1_Kant] ON dbo.LaserData (F1 ASC, Kant ASC) WHERE (Kant IS NOT NULL)
OK, I have found where the error occurs and it has nothing to do with the ExistsLaserData to do. ExistsLaserData works perfectly!
since this is a whole new problem I will make a new question
Thanks for all of your suggestions, I will use some of them!
PS! As a teaser. In the override of SaveChanges event I Trim() all fields that are strings. This does something that make the base.SaveChanges throw an exception...

am using this for Query String to filter the Movies I have in the database there's something wrong

string mid = Request.QueryString["ID"];
if ( db.Movies.Where(i=>i.ID==mid))
{
repMovie.DataSource = db.Movies.Find().ToString();
repMovie.DataBind();
}
Try adding .Any() to return a boolean in your if statement.
Any() returns true if any results are returned by an enumerable object.
if ( db.Movies.Where(i=>i.ID==mid).Any())
{
//...
}
First, db.Movies.Where(i=>i.ID==mid) isn't a boolean. Why are you testing if it's true or false?
Second, repMovie.DataSource = db.Movies.Find().ToString(); has no condition on it. How will that return the right thing? Why don't you do this instead:
(Assuming there's going to be a maximum of one match, ever):
var matchingMovie = db.Movies.FirstOrDefault(i => i.ID == movieId);
if (matchingMovie !== null) {
// you found it in one operation and can work with it now
}
I recommend against variable names like mid. What's that? Anyone else who sees it, or even yourself in a few months, will have no idea and will have to do extra scanning work to figure out its meaning. Use movieId instead.
And for that matter, why are you getting the movieId directly from the querystring yourself? Your MVC action methods should do this for you:
public ActionResult Index(int ID) {
// Lookie! you've automatically gotten the ID from the querystring, and
// you also know it's a non-null integer. If it were null or a non-integer,
// it wouldn't match this route and the client would get a 404, unless you
// had another route to handle those.
}
Alternate ways
int numMid = Convert.ToInt32(mid);
if ( db.Movies.Where(i=>i.ID==numMid).Count()>0)
{
//...
}
or
int numMid = Convert.ToInt32(mid);
if (db.Movies.Any(i=>i.ID==numMid))
{
//...
}

Correct query linq

I already use linq but search id only and it worked perfectly
var obj = (from VAR in db.infos
where VAR.id == 22
select new
{
title = VAR.title,
}).SingleOrDefault();
Label2.Text = obj.title.Trim();
If I try to search by location get a error
var obj = (from VAR in db.infos
where VAR.location.Trim() == "Lim"
select new
{
title = VAR.title.Trim(),
}).SingleOrDefault();
SearchJob.Items.Add(obj.title.Trim());
Label2.Text = obj.title;
Have a error in label2 line
Object reference not set to an instance of an object.
How do I fix it?
if (obj.title != null)
{
SearchJob.Items.Add(obj.title.Trim());
Label2.Text = obj.title;
}
Object reference not set to an instance of an object.
SOLUTION
Change SingleOrDefault() to FirstOrDefault()
You're doing some nasty stuff there, VERY bad habits. For instance this:
var obj = (from VAR in db.infos
where VAR.location.Trim() == "Lim"
select new
{
title = VAR.title.Trim(),
}).SingleOrDefault();
SearchJob.Items.Add(obj.title.Trim());
Label2.Text = obj.title;
Is a nonsense! Let me tell you why:
Always check the data BEFORE you insert it into your database, not AFTER. You're creating a lot of unnecessary overhead this way, which could be avoided altogether. Trim the data before, never after.
Next thing - you need only a single string value, yet you create an anonymous object. WHY? Do this instead:
string title = (from o in db.infos
where o.location == "Lim"
select o.title).SingleOrDefault();
Use SingleOrDefault if you expect a single result or none. However, if you expect multiple results and want only the first, use FirstOrDefault.
As you can see, I'm using o instead of VAR. It's true it doesn't really matter that much, BUT, it's never a good idea to use a word that's very similar to one of the reserved words (var).
If you get an exception Object reference not set to an instance of an object., it means that your query returned a null and you're trying to access a non-existing object. If your query may return null at some point, always check for null when accessing a member!
EDIT
if ( obj.title != null )
is bad too, because you need to check for null the object itself!
if (obj != null)
if you really want to use your bad approach.
I think the error occurred in the query
In first query you have source db.infos
In second you have source db.jobinfos
The source is changed
If we assign empty text to Label it will show, It looks like that obj.title does not exist or you are getting error in your query due to wrong source.
The obj is not returning title field. Check obj by debugging.
Try to skip exception :)
public static class LINQException {
public static void TryExample() {
var LsWithEx = from p in Enumerable.Range(0, 10) select int.Parse("dsfksdj");
var LsSkipEx = (from p in Enumerable.Range(0, 10) select int.Parse("dsfksdj")).SkipExceptions();
}
public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> values)
{
using (var enumerator = values.GetEnumerator())
{
bool next = true;
while (next)
{
try
{ next = enumerator.MoveNext();}
catch
{ continue;}
if (next) yield return enumerator.Current;
}
}
}
}
var obj = (from VAR in db.infos
where VAR.location.Trim() == "Lim"
select new
{
title = VAR.title.Trim(),
}).SkipExce.SingleOrDefault();

Not all code paths return a value

I am having this Linq To SQL query which is taking Customer Category from database.The CustCategory will be defined already.Here is the query.
public IList<string> GetAccountType()
{
using (var db = new DataClasses1DataContext())
{
var acctype = db.mem_types.Select(account=>account.CustCategory).Distinct().ToList();
if (acctype != null)
{
return acctype;
}
}
}
Currently I am getting an error that Not all code paths return a value.If I am always certain that the value is there in the database then do I need to check for null,If I need to check for null then how do I handle this.
Can anyone help me with this.
Any suggestions are welcome.
Since Enumerable.ToList never returns null (see the Return Value section of the documentation), you can safely remove the if.
EDIT: Note that, no matter what your database contains, acctype will never be null:
If no value is found in the database, the return value will be an empty list (which is different than null).
If one record is found and its value is null, the return value will be a valid list with one entry, whose value is null. Still, the list itself is not null.
What happens if:
if (acctype != null)
Is null? What is your method supposed to return?
You need to return something
This is not about LINQ to SQL, the method GetAccountType() must return IList<string>. You should return return acctype; and then check this returned list later using Any(), something like:
if(GetAccountType.Any()){
//not empty
}
How about something like this for a fairly clean and readable solution?:
(Note, updated: removed the check for null, since it would clearly not have any effect).
public IList<string> GetAccountType()
{
var acctype = new List<string>();
using (var db = new DataClasses1DataContext())
{
acctype = db.mem_types.Select(
account=>account.CustCategory).Distinct().ToList();
}
return acctype;
}
You need to return a value from your function:
public IList<string> GetAccountType()
{
using (var db = new DataClasses1DataContext())
{
var acctype = db.mem_types.Select(account=>account.CustCategory).Distinct().ToList();
if (acctype != null)
{
return acctype;
}
}
return acctype;
}

Categories

Resources