tableadapter failed constraints - c#

I'm using a tableadapter in a large project and I keep getting the "Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints." error whenever I call any of my queries on it. I do not have null values and I do have unique primary key values in the result set. Nevertheless, I have tried setting EnforceConstraints to False everywhere in the generated source. I also removed any primary keys using "delete key" option in the context menu for the column. I set AllowDBNull true for all the columns in the tableadapter. The exception still occurs. I have three queries defined under the tableadapter all of which return the same exact same columns (the SQL differs only in the filter expressions used). Researching this issue online, I found the suggestion to set a try/catch in the generated source code to examine the error to determine the exact cause. When I do this, no error is generated at all. The generated source is as follows:
public virtual CyberevToo.ReactionImagesDataTable AllMedia(string MindfileID, string FilePath) {
this.Adapter.SelectCommand = this.CommandCollection[1];
if ((MindfileID == null)) {
throw new global::System.ArgumentNullException("MindfileID");
}
else {
this.Adapter.SelectCommand.Parameters[0].Value = ((string)(MindfileID));
}
if ((FilePath == null)) {
throw new global::System.ArgumentNullException("FilePath");
}
else {
this.Adapter.SelectCommand.Parameters[1].Value = ((string)(FilePath));
}
CyberevToo.ReactionImagesDataTable dataTable = new CyberevToo.ReactionImagesDataTable();
this.Adapter.Fill(dataTable);
return dataTable;
}
The exception is thrown on the "this.Adapter.Fill(dataTable);" line. After modification, the source code is as follows:
public virtual CyberevToo.ReactionImagesDataTable AllMedia(string MindfileID, string FilePath) {
this.Adapter.SelectCommand = this.CommandCollection[1];
if ((MindfileID == null)) {
throw new global::System.ArgumentNullException("MindfileID");
}
else {
this.Adapter.SelectCommand.Parameters[0].Value = ((string)(MindfileID));
}
if ((FilePath == null)) {
throw new global::System.ArgumentNullException("FilePath");
}
else {
this.Adapter.SelectCommand.Parameters[1].Value = ((string)(FilePath));
}
CyberevToo.ReactionImagesDataTable dataTable = new CyberevToo.ReactionImagesDataTable();
try
{
this.Adapter.Fill(dataTable);
}
catch (System.Exception ex) {
System.Console.WriteLine(ex.Message);
}
return dataTable;
}
with a breakpoint set on the line "System.Console.WriteLine(ex.Message);" which never gets reached. With the try/catch in place, the DataTable is returned fine and full of data. Without it, no data is returned at all. When I build and run the program with the try/catch, no exception occurs. When it executes without a try/catch, it fails with the above exception.
Any ideas WHY? I don't want to have to re-code the generated code for all 20 something tableadapters I have in the XSD every time I make a change to one of the definitions!

Related

What can I write as a temporary measure to make a stored procedure throw an exception when invoked?

I'm trying to write a test that makes sure SqlExceptions correctly bubble up in my code. The basic structure is like
MakeTheSprocFailWhenCalled();
try
{
ExecuteSomethingThatCallsASproc();
Assert.Fail("Should never have made it here");
}
catch(Exception e)
{
Assert.AreEqual(typeof(SqlException), e.GetType());
}
finally
{
UndoTheThingIDidInTheFirstLine();
}
and I'm wondering if what I'm trying to do is even possible, and if so, what should I put for
MakeTheSprocFailWhenCalled();
and
UndoTheThingIDidInTheFirstLine();
To mock up your scenario-
MakeTheSprocFailWhenCalled();
try
{
ExecuteSomethingThatCallsASproc();
throw new Exception();
Assert.Fail("Should never have made it here");
}
catch(Exception e)
{
Assert.AreEqual(typeof(SqlException), e.GetType());
}
finally
{
UndoTheThingIDidInTheFirstLine();
}
The throw new Exception(); would throw a generic exception. In your case, it would throw an SQLException anyways.
Test_SQLExceptionBubblesUp()
{
ExecuteSomethingThatCallsASproc(); //to check there is no exception
MakeTheSprocFailWhenCalled();
try
{
ExecuteSomethingThatCallsASproc();
Assert.Fail("Should never have made it here");
}
catch(Exception e)
{
Assert.AreEqual(typeof(SqlException), e.GetType());
}
finally
{
UndoTheThingIDidInTheFirstLine();
}
}
MakeTheSprocFailWhenCalled()
{
//insert a record into testSqlException table
}
UndoTheThingIDidInTheFirstLine()
{
//truncate testSqlException table
}
in your SP:
ALTER PROCEDURE [dbo].[mySqlExceptionPROC]
AS BEGIN
if (select count(*) from testSqlException) > 0
begin
select 1 / 0 --divide by zero exception
end
SELECT 'SP done'
END
If I understood your question correctly, you're looking for a piece of tsql to intentionally break so that you can see if your code is handling errors correctly. If this is not, the case, please stop here and correct me; otherwise, please proceed.
I have a need something along those lines, and I have my go-to error-invoking query which I use. Keep in mind, that you need a query which will parse properly, though not execute properly.
I use
SELECT top 1 1
FROM [<enter any table name here>]
WHERE 1 = 'A'
As for having this fail just when testing, I've seen an approach, introduced to me by Brent Ozar (cannot find reference to that now) which uses a parameter passed into the sproc letting it know whether or not it is debugging or not. You can have a begin/end section in your sproc which will only be executed if the debug parameter is set to 1 (debugging).
This way, you can pass a 1 for debugging and a 0 once you get to production, and only execute the aforementioned code snippet if they debug flag = 1.

C# error "Not all code paths return a value"

I translated this part of the code from vb to c# and giving me this error message. "Not all code paths return a value". What is the problem? Thanks in advance.
public DataSet LoadSearchDataSet(string strConnection, string strSQL)
{
//The purpose of this function is to create and populate a data
//set based on a SQL statement passed in to the function.
try
{
DataSet dsData = new DataSet();
//call the table in the local dataset "results" since the values
//may be coming from multiple tables.
string strTableName = "Results";
bool blnRunStoredProc = false;
dsData = PopulateDataSetTable(strConnection, strTableName, strSQL, blnRunStoredProc, dsData);
WriteSampleDataToOutputWindow(dsData);
//return the data set to the calling procedure
return dsData;
}
catch
{
//error handling goes here
UnhandledExceptionHandler();
}
}
You are missing the return value in the case the code throws an exception.
public DataSet LoadSearchDataSet(string strConnection, string strSQL)
{
//The purpose of this function is to create and populate a data
//set based on a SQL statement passed in to the function.
DataSet dsData = new DataSet();
try
{
//call the table in the local dataset "results" since the values
//may be coming from multiple tables.
string strTableName = "Results";
bool blnRunStoredProc = false;
dsData = PopulateDataSetTable(strConnection, strTableName, strSQL, blnRunStoredProc, dsData);
WriteSampleDataToOutputWindow(dsData);
}
catch
{
//error handling goes here
UnhandledExceptionHandler();
}
//return the data set to the calling procedure
return dsData;
}
If an exception occurs in your try block before the return statement, the catch is executed and that does not return anything, because you did not tell it to.
You can do one of these:
Return a value from the catch block. Do this only if it makes sense and you have a sensible value you can return. Be aware that returning null is a usual source of bugs and there are patterns out there to avoid just that.
Re-throw the exception that occurred, if you cannot do anything at this point about it (and return an object that makes sense). You can do this by adding a line that says: throw;
Throw a different error - You can package the original exception in a new one, providing extra details about the context, if necessary.
You need to add a return statement after your catch clause!
In case of an exception inside your try catch clause, you won't return a value. And that's exactly what your error is indicating.
This is a common error message in functions, as functions are designed to return some value. If your code passes the catch section, it will reach the end of the function without returning anything, thats where you need to return the value.
rewrite like this:
DataSet dsData = null;
try
{
//call the table in the local dataset "results" since the values
//may be coming from multiple tables.
string strTableName = "Results";
bool blnRunStoredProc = false;
dsData = PopulateDataSetTable(strConnection, strTableName, strSQL, blnRunStoredProc, dsData);
WriteSampleDataToOutputWindow(dsData);
}
catch
{
//error handling goes here
UnhandledExceptionHandler();
}
//return the data set to the calling procedure
return dsData;
You can resolve this issue by :
change the function return to VOID (if you does not return something)
give return keyword with variable name before end function
This is because in the case of any exception occurs,the exception will thrown to the catch, in that case the code will not return any value. so you have to return some value from the catch to avoid this issue
Replace the catch with this:
catch
{
//error handling goes here
UnhandledExceptionHandler();
return new DataSet();
}
It is must to return proper value in any case. so try to maintain try catch block with return value or outside of try/catch block if nothing to return in try / catch block.

Update only works in debug mode

I'm new to using entity as a data layer between MVC and SQL Server, so I apologize up front if what I'm doing is bad practice.
Let me start by sharing the code that is handling the update.
Update Delivery:
public bool One(Delivery toUpdate)
{
using (var dbContext = new FDb())
{
try
{
var deliveryInDb = this.dbTable(dbContext).Single(x => x.DeliveryId == toUpdate.DeliveryId);
dbContext.Entry(deliveryInDb).CurrentValues.SetValues(toUpdate);
//removal first
List<DeliveryDay> currentDays = FEngineCore.DeliveryDay.Get.ForValue((x => x.DeliveryId), toUpdate.DeliveryId);
List<DeliveryTime> currentTimes = FEngineCore.DeliveryTime.Get.ForValue((x => x.DeliveryId), toUpdate.DeliveryId);
//remove delivery days that are not needed
foreach (var curDay in currentDays)
{
if (!toUpdate.DeliveryDays.Select(x => x.DeliveryDayId).Contains(curDay.DeliveryDayId))
{
FEngineCore.DeliveryDay.Delete.One((x => x.DeliveryDayId), curDay.DeliveryDayId);
deliveryInDb.DeliveryDays.Remove(curDay);
}
}
//remove delivery times that are not needed
foreach (var curTime in currentTimes)
{
if (!toUpdate.DeliveryTimes.Select(x => x.DeliveryTimeId).Contains(curTime.DeliveryTimeId))
{
FEngineCore.DeliveryTime.Delete.One((x => x.DeliveryTimeId), curTime.DeliveryTimeId);
deliveryInDb.DeliveryTimes.Remove(curTime);
}
}
foreach (var day in toUpdate.DeliveryDays)
{
if (day.DeliveryDayId == 0)
{
dbContext.DeliveryDays.Add(day);
}
else
{
if (dbContext.DeliveryDays.Local.Any(e => e.DeliveryDayId == day.DeliveryDayId))
{
dbContext.Entry(dbContext.DeliveryDays.Local.First(e => e.DeliveryDayId == day.DeliveryDayId)).CurrentValues.SetValues(day);
dbContext.Entry(dbContext.DeliveryDays.Local.First(e => e.DeliveryDayId == day.DeliveryDayId)).State = EntityState.Modified;
}
else
{
DeliveryDay modDay = new DeliveryDay
{
DayOfWeek = day.DayOfWeek,
DeliveryDayId = day.DeliveryDayId,
DeliveryId = day.DeliveryId,
Interval = day.Interval
};
dbContext.DeliveryDays.Attach(modDay);
dbContext.Entry(modDay).State = EntityState.Modified;
}
deliveryInDb.DeliveryDays.Add(day);
}
}
foreach (var time in toUpdate.DeliveryTimes)
{
if (time.DeliveryTimeId == 0)
{
dbContext.DeliveryTimes.Add(time);
}
else
{
if (dbContext.DeliveryTimes.Local.Any(e => e.DeliveryTimeId == time.DeliveryTimeId))
{
dbContext.Entry(dbContext.DeliveryTimes.Local.First(e => e.DeliveryTimeId == time.DeliveryTimeId)).CurrentValues.SetValues(time);
dbContext.Entry(dbContext.DeliveryTimes.Local.First(e => e.DeliveryTimeId == time.DeliveryTimeId)).State = EntityState.Modified;
}
else
{
DeliveryTime modTime = new DeliveryTime
{
DeliveryId = time.DeliveryId,
DeliveryLocationId = time.DeliveryLocationId,
DeliveryTimeId = time.DeliveryTimeId,
DropoffTime = time.DropoffTime
};
dbContext.DeliveryTimes.Attach(modTime);
dbContext.Entry(modTime).State = EntityState.Modified;
}
deliveryInDb.DeliveryTimes.Add(time);
}
}
dbContext.SaveChanges();
dbContext.Entry(deliveryInDb).State = EntityState.Detached;
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return false;
}
}
}
Let me continue by explaining that the delivery object has 2 children; DeliveryTime and DeliveryDay. The issue that arises happens when I try to remove one deliveryTime and modify nothing else. The end result of running the code normally (not in debug) is that the deliveryTime is in fact not removed. Here's the interesting thing guys, when I debug it and go through the break points, everything works as expected!
Let me continue by posting the code that is running behind the removal method of the deliveryTime (actually all entity objects in my system).
public bool One<V>(Expression<Func<T, V>> property, V value) where V : IComparable
{
using (var dbContext = new FoodsbyDb())
{
try
{
T toDelete;
//get the body as a property that represents the property of the entity object
MemberExpression entityPropertyExpression = property.Body as MemberExpression;
//get the parameter that is representing the entity object
ParameterExpression entityObjectExpression = (ParameterExpression)entityPropertyExpression.Expression;
//represent the value being checked against as an expression constant
Expression valueAsExpression = Expression.Constant(value);
//check the equality of the property and the value
Expression equalsExpression = Expression.Equal(entityPropertyExpression, valueAsExpression);
//create an expression that takes the entity object as a parameter, and checks the equality using the equalsExpression variable
Expression<Func<T, bool>> filterLambda = Expression.Lambda<Func<T, bool>>(equalsExpression, entityObjectExpression);
toDelete = this.dbTable(dbContext)
.SingleOrDefault(filterLambda);
if (toDelete != null)
{
this.dbTable(dbContext)
.Remove(toDelete);
dbContext.SaveChanges();
return true;
}
return false;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return false;
}
}
}
The code above is obviously generic, and it handles all my entity objects. I have tested it in and out and know for sure the problem does not lie in there. I thought it would be helpful to post it so you all can have a full understanding of what's going on.
Here's my best guess as to what's going on:
The reference to the removed deliveryTime still exists when the database context is saved, but when I debug, the system has enough time to remove the context.
Here was one of my attempted solutions:
Remove all references to the children objects immediately after setting currentDays and currentTimes and then proceeding to add them back to deliveryInDb as you enumerate through them.
Because I am new to all of this, if you see some bad practice along with the solution, I wouldn't mind constructive criticism to improve my programming method.
I actually encountered this issue in a project at work. The project is an older MVC4 project using EF 6.1.
In our situation, a simple update attempting to set a related entity property to null was failing to actually set it to null while running the web app normally (in debug mode). When setting a break point on the line of code that sets the property to null the database would be updated as expected, though. So, the update was working when a break point was in place but not working when allowed to run normally.
Using an EF interceptor, we could see that, with the break point in place, the update query was going through as expected.
Now, in our situation the related entity was using the virtual keyword to allow for lazy loading. I think this is the root of the issue. When a break point is present, EF has enough time to both lazily load that related entity and evaluate whatever it needs to evaluate and finally set it to null. When running without a break point, I think EF gets caught up trying to lazily load that entity and therefore fails to think it needs to be updated. To be clear, I was both accessing the related entity property for the first time and setting it null using a one-liner of code.
foo.Bar = null;
I resolved this issue, in our scenario, by accessing that property at least once prior to setting it to null so that EF is forced to load it. With it loaded, setting it to null seems to work as intended now. So again, to be clear, I think the issue is a combo of lazy loading and the one-liner of code both accessing that property for the first time and assigning it to null.
It appears that you're using multiple instances of your DbContext, which are not synchronized.
The solution would be to use a single instance, and pass that instance between your methods.

Exception handling design from class libarary

I'm looking for some program design guidance.
I have a class library that handles data in a database. I have a winforms app that is the presentation layer for the user to input and manage data. Say for example the user inputs some data and attempts to save it. From the winforms app I do something like:
MyTool theTool = new MyTool();
MyTool.FirstName = this.Textbox1.Text;
MyTool.LastName = this.Textbox2.Text;
//etc...
int result = MyTool.SaveData(); //result is the ID of the inserted record.
MyTool is a type in my class library. Within this type I would have:
public int SaveData()
{
if (IsReadyForInput())
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else
{
throw new ArgumentException("One or more arguments prevented saving the data");
}
return theID
}
private bool IsReadyForInput()
{
if (this.FirstName.Length == 0)
{ return false; }
if (this.LastName.Length == 0)
{return false;}
return true;
}
Now, what I'm interested in is the best design on how exception handling should work. For example the above method is not specific at all so the user doesn't know what's wrong. So I could rewrite this to do something like:
public void SaveData()
{
string errMess = IsReadyForInput();
if (errMess.Length == 0)
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else {
throw new ArgumentException(errMess);
}
return theID
}
private string IsReadyForInput()
{
if (this.FirstName.Length == 0)
{ return "Specify a first name"; }
if (this.LastName.Length == 0)
{return "Specify a last name";}
return true;
}
However it just doesn't seem a very elegant (or fast) method to be comparing string lengths to find an error message. I had tried writing something like:
public void SaveData()
{
ValidateInput();
//..open a DB connection and save out the data
return theID
}
private void ValidateInput()
{
if (this.FirstName.Length == 0)
{ throw new ArgumentException("Specify a first name"; }
if (this.LastName.Length == 0)
{throw new ArgumentException("Specify a first name"; }
}
The problem with this is that the exception is actually thrown by ValidateInput when the front end is calling "SaveData", so when the exception reaches the top, to me, it would seem less clear (especially if there are multiple ways of calling "ValidateInput()" from within MyTool).
Additionally I am not sure what the best way to handle the exception on the front end would be because, if an error is thrown, the ID is never returned.
I guess I am just looking for some guidance on how to handle this situation and validation/error handling in general. Thanks for any help.
The first thing I wonder about is whether you need to throw an exception at all when ordinary control flow might be enough:
if (IsReadyForInput())
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else
{
//..do whatever you need in case of invalid input
}
The obvious problem with this suggestion is that we are in a method somewhere in your class library, and some of the desired effects (displaying warnings to the user, etc.) happen in the WinForms layer. That, however, suggests a better solution; namely, to do the validation in the WinForms code:
if (IsReadyForInput())
{
int result = theTool.SaveData();
//...and whatever else should happen.
}
else
{
//..do whatever you need in case of invalid input
}
The above approach is simpler and makes the parts of your program less dependent on each other (as MyTool doesn't need to care about validation of user input) when compared to, e.g., throwing an exception or using special return values to signal failure.
Take a look at FluentValidation (http://fluentvalidation.codeplex.com/). I think it's what you're looking for.
With it you can define your validation rules and call its validation methods. It will return a full list of potential validation errors without causing exceptions to be thrown in your code.

Annoying SQL exception, probably due to some code done wrong

I started working on this "already started" project, and I'm having a really annoying error when trying to execute some interactions with SQL Server 2008:
The server failed to resume the
transaction. Desc.:
One of these errors I get in this specific method call:
The aspx.cs Call:
busProcesso openProcess = new busProcesso(pProcessoId);
try
{
if (openProcess.GetDocument() == null)
{
//Irrelevant code.
}
}
catch{ //... }
The Business class (relevant part):
public class busProcesso : IbusProcesso
{
public Processo vProcesso { get; set; }
RENDBDataContext db;
public busProcesso()
{
vProcesso = new Processo();
}
public busProcesso(decimal pProcessoId)
{
db = new RENDBDataContext();
try
{
vProcesso = db.Processos.SingleOrDefault(x => x.Id == pProcessoId);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public string GetDocument()
{
try
{
string document = null;
foreach (Processo_has_Servico ps in ListaServicosProcesso())
{
if (ps.Servico.Document != null) //Get the error right at this line.
{
document = ps.Servico.Document;
}
}
return document ;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public IQueryable<Processo_has_Servico> ListaServicosProcesso()
{
db = new RENDBDataContext();
try
{
return from ps in db.Processo_has_Servicos
join s in db.Servicos on ps.Servico_Id equals s.Id
where ps.Processo_Id == vProcesso.Id
select ps;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
}
As I said, the error occurs right at the line:
if (ps.Servico.Document != null) from the GetDocument() method.
Opening SQL Server Activity Monitor, I see there is a process for my database (.Net SqlClient Data Provider)
After some time/use (when I start to get the "server failed to resume the transaction" error), I go to the SQL Server Activity Monitor and there's around 5 or 6 more identical processes that weren't killed and (probably) should've been. When I manually kill them, the error stops for a while, until it starts again.
I'm not really good at working in OO and all, so I'm probably missing something, maybe some way to close one of these connections. Also, any help/tip about this structure will be welcome.
PS. The error doesn't happen everytime. Sometimes it runs just perfectly. Then it starts to give the error. Then it stops. Sometimes it happens just once.. pretty weird.
The code in ListaServicosProcesso is creating the context db. Then it is returning an IQueryable.
At this point no request has been sent to the database.
Then there is a for each in the code. At this point EF says "I need to get the data from the database". So it tries to get the data.
But the context db is now out of scope, so it crashes, on the first line that tries to use the data.
There are 2 ways to get around this:
return a list from ListaServicosProcesso, this will force the database call to execute
move the for each into ListaServicosProcesso
Edit
Pharabus is correct db is not out of scope. The problem is here:
db = new RENDBDataContext();
A new instance of the context is being created without the old one being disposed. Try Dispose of db at the end of ListaServicosProcesso. Even better place db in a using statement. But then the foreach must be moved inside the using statement.
Here's a couple of ideas to try.
1/ You can attach SQL server profiler to see the query that is being executed, which will allow you to copy and paste that query to see the data that is in the database. This might be help.
2/ You never check whether ps.Servico is null - you jump straight to ps.Servico.Document. If ps.Servico is null then you will get a null reference exception if you try to access any properties on that object.
I'm not sure of the exact cause of the error you're seeing (if you Google it, the references are all over the place...), but there are a few things you could improve in your code and I've found that just cleaning things up a bit often makes problems go away. Not always, but often.
I agree with the other answerers that it would help to keep better track of your DataContext(s). For example in you're creating it once in the constructor, then again in ListaServicosProcesso(). At that point vProcesso is on one DataContext and other entities will be on another, which gets messy.
I think you could simplify the whole thing a bit, for example you could combine GetDocument() and ListaServicosProcesso() like this:
public string GetDocument()
{
try
{
// Are you sure vProcesso is not null?
if (vProcesso == null)
return null;
// Only create the context if it wasn't already created,
if (db == null)
db = new RENDBDataContext();
return db.Processo_has_Servicos
.Where(ps => ps.Processo_Id == vProcesso.Id && ps.Servico.Document != null)
.Select(ps => ps.Servico.Document) // use an implicit join
.SingleOrDefault();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}

Categories

Resources