Essentially what the title says, for whatever reason when I call clientContext.ExecuteQuery(); and for example the list the data is going into has a missing column, I don't get an exception, it actually just runs as expected and I have to go and investigate what might have caused the data to not appear.
The NuGet package i'm using is Microsoft.SharePoint2016.CSOM version 16.0.4690.1000
Any hints, or suggestions to point me in the right direction appreciated. It's entirely possible I'm being a bit dim here.
Here's the full code block I'm using for updating list items:
public override object UpdateEntity(object entity)
{
if (entity == null)
{
// if the definition is null throw argument null exception.
throw new ArgumentNullException(nameof(SharePointDefinition));
}
// check for incorrect type being passed in that we can still handle
if (entity is List<SharePointDefinition> definitions)
{
return UpdateEntities(definitions);
}
ExceptionHandlingScope exceptionScopeFetch = new ExceptionHandlingScope(clientContext);
ExceptionHandlingScope exceptionScopeSubmit = new ExceptionHandlingScope(clientContext);
// run single definition submit to SP.
if (entity is SharePointDefinition definition)
{
// variables.
IntegrationEventLog log = new IntegrationEventLog();
EventInformation ei = new EventInformation();
List list = null;
ListItemCollection listItemCol = null;
using (exceptionScopeFetch.StartScope())
{
using (exceptionScopeFetch.StartTry())
{
// get the required list
list = clientContext.Web.Lists.GetByTitle(definition.ListName);
// create query
listItemCol = list.GetItems(CamlQuery.CreateAllItemsQuery());
// set these items for retrieval.
clientContext.Load(listItemCol);
}
using (exceptionScopeFetch.StartCatch())
{
// Assume that if there's an exception, it can only be
// because there is no list with the specified title, so report this back.
if (exceptionScopeFetch.HasException)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Hit SharePoint exception handler during list and data pull: Message: {exceptionScopeFetch.ErrorMessage}",
StackTrace = exceptionScopeFetch.ServerStackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
}
}
using (exceptionScopeFetch.StartFinally())
{
//
}
}
// get item instances first
try
{
clientContext.ExecuteQuery();
}
catch (Exception genEx)
{
// return failure log.
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = "Errored trying to get data from SharePoint list ready for update operation; see stacktrace for more information.",
StackTrace = genEx.StackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
return false;
}
// this is the column we want to overwrite.
var comparisonColumn = definition.UpdateIdentifier ?? "";
//List col to dict
var listItems = listItemCol.Cast<ListItem>().ToList();
// Now we know if we were able to retrieve existing data, perform submit.
using (exceptionScopeSubmit.StartScope())
{
using (exceptionScopeSubmit.StartTry())
{
// loop through our rows
foreach (var row in definition.RowData)
{
int existingItemIndex = -1;
// see if the row exists already
if (!string.IsNullOrEmpty(comparisonColumn) && listItems.Count != 0)
{
existingItemIndex = listItems.FindIndex(x => x[comparisonColumn].ToString() == row[comparisonColumn]);
}
if (existingItemIndex != -1 && listItems.Count != 0)
{
// item exists - loop through our row columns
foreach (var keyValuePair in row)
{
// they key relates to a column, the Value to the rows colum Value.
listItems[existingItemIndex].ParseAndSetFieldValue(keyValuePair.Key, keyValuePair.Value);
}
// update this item
listItems[existingItemIndex].Update();
}
else
{
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
ListItem newItem = list.AddItem(itemCreateInfo);
// loop through our row columns
foreach (var keyValuePair in row)
{
// they key relates to a column, the Value to the rows colum Value.
newItem[keyValuePair.Key] = keyValuePair.Value;
}
newItem.Update();
}
}
}
using (exceptionScopeSubmit.StartCatch())
{
// Assume that if there's an exception, it can only be
// because there is no list with the specified title, so report this back.
if (exceptionScopeFetch.HasException)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Error at SharePoint exception handler during submit to list: Message: {exceptionScopeFetch.ErrorMessage}",
StackTrace = exceptionScopeFetch.ServerStackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
}
}
using (exceptionScopeSubmit.StartFinally())
{
//
}
}
// try to execute submit.
try
{
clientContext.ExecuteQuery();
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentSuccess,
LoggingSeverity = LoggingSeverity.Information,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = "No exceptions were thrown from the Execution process.",
StackTrace = "",
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Information;
log.EventID = LoggingSeverity.Information;
log.Message = JsonConvert.SerializeObject(ei);
}
catch (Exception genEx)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Data failed to be updated within SharePoint - {genEx.Message} - see stacktrace for more information.",
StackTrace = genEx.StackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
return false;
}
AddToLog(log);
return true;
}
else
{
// If a different definition type is passed in throw an appropriate exception.
// This should be caught at runtime only.
throw new TypeLoadException(nameof(SharePointDefinition));
}
}
I checked the code you posted and I see that you are updating the list of objects, in your case listItems, instead of a ListItem in ListItemCollection, in your case listItemCol.
To be more clear, I believe you can try to replace listItems with listItemCol.
For instance, instead of:
listItems[existingItemIndex].ParseAndSetFieldValue(keyValuePair.Key, keyValuePair.Value);
use
listItemCol[existingItemIndex][keyValuePair.Key] = keyValuePair.Value;
So I went away and re-read a lot of documentation and looked over some examples, and I wondered why the exception handler never returned errors even though it's obvious there were issues with the query being executed. If you look at the Microsoft documentation and their example here you'll see that they don't show you how to use exceptionScopeSubmit.HasException component of the exception scope object. Which lead to a really stupid assumption on my part. It turns out that the exception block runs on the SharePoint server and should be used to fix issues you might have caused during an expected exception in your query.
Not only that but wrapping the ExecuteQuery in the try catch is redundant when using an exception scope as it means that method will no longer throw an exception. You actually have to assess exceptionScopeSubmit.HasException after the execution to pull back some more detailing information on errors reported by the SharePoint server side execution of your query.
So now I'm using it as below, and I can get detailed error information without having to do some stupid manual debugging which would easily take me hours to track down silly issues. So in case anyone stumbles across this having the same issues, I hope it helps.
ExceptionHandlingScope exceptionScopeFetch = new ExceptionHandlingScope(clientContext);
// variables.
IntegrationEventLog log = new IntegrationEventLog();
EventInformation ei = new EventInformation();
List list = null;
ListItemCollection listItemCol = null;
using (exceptionScopeFetch.StartScope())
{
using (exceptionScopeFetch.StartTry())
{
// get the required list
list = clientContext.Web.Lists.GetByTitle(definition.ListName);
// create query
listItemCol = list.GetItems(CamlQuery.CreateAllItemsQuery());
// set these items for retrieval.
clientContext.Load(listItemCol);
}
using (exceptionScopeFetch.StartCatch())
{
//
}
using (exceptionScopeFetch.StartFinally())
{
//
}
}
// get item instances first
clientContext.ExecuteQuery();
if (exceptionScopeSubmit.HasException)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Error at SharePoint exception handler during submit to list: Message: {exceptionScopeFetch.ErrorMessage}",
StackTrace = exceptionScopeFetch.ServerStackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
}
Related
I'm hoping someone can help me with this issue. I have two methods that insert a document into a Cosmos DB. One works each and every time I run it. The other gets as far as CreateDatabaseIfNotExistsAsync and kicks out of the method and returns to the calling method. The ItemReponse objects Status property says "WaitingForActivation".
I will say that this logic did work once and now (with no changes) it does not. Below is the code that dies. First the Unit test:
public void AddPerson()
{
var logger = Mock.Of<ILogger<Person>>();
var appset = Mock.Of<IAppSettings>();
appset.DatabaseName = "PersonsDB";
appset.ContainerName = "PersonsContainer";
appset.EndpointUrl = "https://localhost:8081";
appset.AuthorizationKey = "somesecretkey";
Person person = new Person()
{
id = Guid.NewGuid().ToString(),
Address_line_1 = "1932 Alakea St",
Address_line_2 = "",
Birth_Date = "2020-01-01",
Gender = "m",
Patient_First_Name = "John",
Patient_Last_Name = "Ridley",
Hospital_Code = "Queens Med",
Rec_ID = "1111111111",
VER_CRM_ID = "22222222",
VER_EMAIL = "JR#noemail.com",
};
PersonCosmos personCosmos = new PersonCosmos(logger, appset);
var myresult = personCosmos.PutPersonData(person);
Assert.True(myresult.Exception == null, "Row added");
}
Let me add that I am running the Cosmos Emulator hence the localhost url. Now for the code that dies.
public async Task<ItemResponse<Person>> PutPersonData(Person persondata)
{
this.cosmosClient = new CosmosClient(EndpointUri, PrimaryKey);
this.database = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(DatabaseName);
this.container = await this.database.CreateContainerIfNotExistsAsync(ContainerName, "/Hospital_Code");
ItemResponse<Person> PutResponse = null;
try
{
// Read the item to see if it exists.
PutResponse = await this.container.ReadItemAsync<Person>(persondata.id.ToString(), new PartitionKey(persondata.Hospital_Code ));
return PutResponse;
}
catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
// Create an item in the container representing the Appointment. Note we provide the value of the partition key for this item, which is "Hospital_Code"
PutResponse = await this.container.CreateItemAsync<Person>(persondata, new PartitionKey(persondata.Hospital_Code));
return PutResponse;
}
catch (Exception ex)
{
// Create an item in the container representing the object. Note we provide the value of the partition key for this item, which is "Hospital_Code"
_logger.LogError($"Error in {0} at {1} " + ex.Message, System.Reflection.MethodBase.GetCurrentMethod().Name, DateTime.UtcNow.ToLongTimeString());
return PutResponse;
}
}
You are mixing sync and async in your code here.
Use await on this line.
var myresult = **await** personCosmos.PutPersonData(person);
and also this calling function should be async as well
public void AddPerson()
I am using active directory and want a list of all users, basically in dotnet core. But I am receiving an exception:
Search result reference received, and referral following is off
Below is my code.
LdapSearchResults lsc = lc.Search("DC = xyz, DC = local", LdapConnection.SCOPE_ONE , "(|(objectClass = person)(objectClass = user))", null, false);
Necromancing - just in case the links go dark.
To fix it in your application, set ReferralFollowing to true.
if you get the message
Search result reference received, and referral following is off
, add
Novell.Directory.Ldap.LdapSearchConstraints cons = lc.SearchConstraints;
cons.ReferralFollowing = true;
lc.Constraints = cons;
to your code.
Example:
public static void GetUsers()
{
System.Collections.Generic.List<ARSoft.Tools.Net.Dns.SrvRecord> lsLdap = GetLdap();
ARSoft.Tools.Net.Dns.SrvRecord ldap = lsLdap[0];
string[] attrs = new string[] { "cn", "distinguishedName", "sAMAccountName", "userPrincipalName", "displayName", "givenName", "sn", "mail", "mailNickname", "memberOf", "homeDirectory", "msExchUserCulture" };
// CN = Common Name
// OU = Organizational Unit
// DC = Domain Component
string searchBase = "DC=cor,DC=local";
string searchFilter = "(&(objectClass=user)(objectCategory=person))";
string ldapHost = MySamples.TestSettings.ldapHost;
int ldapPort = MySamples.TestSettings.ldapPort;//System.Convert.ToInt32(args[1]);
string loginDN = MySamples.TestSettings.loginDN; // args[2];
string password = MySamples.TestSettings.password; // args[3];
Novell.Directory.Ldap.LdapConnection lc = new Novell.Directory.Ldap.LdapConnection();
int ldapVersion = Novell.Directory.Ldap.LdapConnection.Ldap_V3;
try
{
// connect to the server
lc.Connect(ldap.Target.ToString(), ldap.Port);
// bind to the server
lc.Bind(ldapVersion, loginDN, password);
Novell.Directory.Ldap.LdapSearchConstraints cons = lc.SearchConstraints;
cons.ReferralFollowing = true;
lc.Constraints = cons;
// To enable referral following, use LDAPConstraints.setReferralFollowing passing TRUE to enable referrals, or FALSE(default) to disable referrals.
Novell.Directory.Ldap.LdapSearchResults lsc = lc.Search(searchBase,
Novell.Directory.Ldap.LdapConnection.SCOPE_SUB,
searchFilter,
attrs,
false,
(Novell.Directory.Ldap.LdapSearchConstraints)null);
while (lsc.HasMore())
{
Novell.Directory.Ldap.LdapEntry nextEntry = null;
try
{
nextEntry = lsc.Next();
}
catch (Novell.Directory.Ldap.LdapReferralException eR)
{
// https://stackoverflow.com/questions/46052873/ldap-referal-error
// The response you received means that the directory you are requesting does not contain the data you look for,
// but they are in another directory, and in the response there is the information about the "referral" directory
// on which you need to rebind to "redo" the search.This principle in LDAP are the referral.
// https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bp31k5d.html
// To enable referral following, use LDAPConstraints.setReferralFollowing passing TRUE to enable referrals, or FALSE (default) to disable referrals.
// are you sure your bind user meaning
// auth.impl.ldap.userid=CN=DotCMSUser,OU=Service Accounts,DC=mycompany,DC=intranet
// auth.impl.ldap.password = mypassword123
// has permissions to the user that is logging in and its groups?
System.Diagnostics.Debug.WriteLine(eR.LdapErrorMessage);
}
catch (Novell.Directory.Ldap.LdapException e)
{
// WARNING: Here catches only LDAP-Exception, no other types...
System.Console.WriteLine("Error: " + e.LdapErrorMessage);
// Exception is thrown, go for next entry
continue;
}
var atCN = nextEntry.getAttribute("cn");
var atUN = nextEntry.getAttribute("sAMAccountName");
var atDN = nextEntry.getAttribute("distinguishedName");
var atDIN = nextEntry.getAttribute("displayName");
if (atCN != null)
System.Console.WriteLine(atCN.StringValue);
if (atUN != null)
System.Console.WriteLine(atUN.StringValue);
if (atDN != null)
System.Console.WriteLine(atDN.StringValue);
if (atDIN != null)
System.Console.WriteLine(atDIN.StringValue);
System.Console.WriteLine("\n" + nextEntry.DN);
Novell.Directory.Ldap.LdapAttributeSet attributeSet = nextEntry.getAttributeSet();
System.Collections.IEnumerator ienum = attributeSet.GetEnumerator();
while (ienum.MoveNext())
{
Novell.Directory.Ldap.LdapAttribute attribute = (Novell.Directory.Ldap.LdapAttribute)ienum.Current;
string attributeName = attribute.Name;
string attributeVal = attribute.StringValue;
System.Console.WriteLine(attributeName + "value:" + attributeVal);
}
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
}
finally
{
// disconnect with the server
lc.Disconnect();
}
}
You have to activate the behaviour which will follow the referral returned by the directory.
The response you received means that the directory you are requesting does not contain the data you look for, but they are in another directory, and in the response there is the information about the "referral" directory on which you need to rebind to "redo" the search. This principle in LDAP are the referral.
I don't know how to do it in C#, but maybe have a look at :
https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bp31k5d.html
I have a scenario in CRM where I need to update existing accounts with their Vat and Registration number. There is well over 30 thousand accounts in the system. I am trying to update using the CRM SDK API but I am battling to figure out how to perform the actual update. The vat number and reg have been provided to me in a spreadsheet with their corresponding number, please note that the accounts are already in CRM so I just need to update the correct account with its Vat and Reg number, How can I do this in CRM, please advice on my code below:
public static void UpdateAllCRMAccountsWithVATAndRegistrationNumber(IOrganizationService service)
{
QueryExpression qe = new QueryExpression();
qe.EntityName = "account";
qe.ColumnSet = new ColumnSet("account", "new_vatno", "new_registrationnumber");
qe.Criteria.AddCondition("accountnumber", ConditionOperator.In,"TA10024846", "TA10028471", "TA20014015", "TA4011652", "TA4011557");
EntityCollection response = service.RetrieveMultiple(qe);
foreach (var acc in response.Entities)
{
acc.Attributes["new_vatno"] = //this is where I am struggling to figure out how I am gong to match the records up,
acc.Attributes["new_registrationnumber"] = //this is where I am struggling to figure out how I am gong to match the records up,
service.Update(acc);
}
}
How am I going to ensure that I update the correct records. I have the vat and reg numbers for the accounts in a spreadsheet, please see example image below. Can I please get advised here. Thanks.
I would load the list of VAT updates from the spreadsheet into a dictionary and then load the 30k record from CRM into memory. Then I would match them up and use ExecuteMultipleRequest to do the updates. Alternatively, you could query CRM using the account numbers (if the list is small enough.) I made the assumption you had thousands of updates to do across the record set of 30k. Note, if the Account record size was very large and couldn't be loaded into memory you would need to do account number queries.
Here is the rough code for the basic solution (I haven't tested, method should be split up, and there is minimal error handling):
public class VatInfo
{
public string RegistrationNumber;
public string TaxNumber;
public static Dictionary<string, VatInfo> GetVatList()
{
//TODO: Implement logic to load CSV file into a list. Dictionary key value should be Account Number
throw new NotImplementedException();
}
}
public class UpdateVatDemo
{
public const int maxBatchSize = 100;
public static void RunVatUpdate(IOrganizationService conn)
{
var vats = VatInfo.GetVatList();
var pagingQuery = new QueryExpression("account");
pagingQuery.ColumnSet = new ColumnSet("accountnumber");
Queue<Entity> allEnts = new Queue<Entity>();
while (true)
{
var results = conn.RetrieveMultiple(pagingQuery);
if (results.Entities != null && results.Entities.Any())
results.Entities.ToList().ForEach(allEnts.Enqueue);
if (!results.MoreRecords) break;
pagingQuery.PageInfo.PageNumber++;
pagingQuery.PageInfo.PagingCookie = results.PagingCookie;
}
ExecuteMultipleRequest emr = null;
while (allEnts.Any())
{
if (emr == null)
emr = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
var ent = allEnts.Dequeue();
if (vats.ContainsKey(ent.GetAttributeValue<string>("accountnumber")))
{
var newEnt = new Entity("account", ent.Id);
newEnt.Attributes.Add("new_vatno", vats[ent.GetAttributeValue<string>("accountnumber")].TaxNumber);
newEnt.Attributes.Add("new_registrationnumber", vats[ent.GetAttributeValue<string>("accountnumber")].RegistrationNumber);
emr.Requests.Add(new UpdateRequest() { Target = newEnt });
}
if (emr.Requests.Count >= maxBatchSize)
{
try
{
var emResponse = (ExecuteMultipleResponse) conn.Execute(emr);
foreach (
var responseItem in emResponse.Responses.Where(responseItem => responseItem.Fault != null))
DisplayFault(emr.Requests[responseItem.RequestIndex],
responseItem.RequestIndex, responseItem.Fault);
}
catch (Exception ex)
{
Console.WriteLine($"Exception during ExecuteMultiple: {ex.Message}");
throw;
}
emr = null;
}
}
}
private static void DisplayFault(OrganizationRequest organizationRequest, int count,
OrganizationServiceFault organizationServiceFault)
{
Console.WriteLine(
"A fault occurred when processing {1} request, at index {0} in the request collection with a fault message: {2}",
count + 1,
organizationRequest.RequestName,
organizationServiceFault.Message);
}
}
Updating the fetched entity is bound to fail because of its entity state, which would not be null.
To update the fetched entities, you need to new up the entity:
foreach (var acc in response.Entities)
{
var updateAccount = new Entity("account") { Id = acc.Id };
updateAccount .Attributes["new_vatno"] = null; //using null as an example.
updateAccount .Attributes["new_registrationnumber"] = null;
service.Update(acc);
}
Code below shows how I managed to get it righy. forst let me explain. I imported my records into a seperate SQL table, in my code I read that table into a list in memory, I then query CRM accounts that need to be updated, I then loop though each account and check if the account number in CRM matches the account number from my sql database, if it matches, I then update the relevant Reg no and Vat no, See code below:
List<Sheet1_> crmAccountList = new List<Sheet1_>();
//var crmAccount = db.Sheet1_.Select(x => x).ToList().Take(2);
var crmAccounts = db.Sheet1_.Select(x => x).ToList();
foreach (var dbAccount in crmAccounts)
{
CRMDataObject modelObject = new CRMDataObject()
{
ID = dbAccount.ID,
Account_No = dbAccount.Account_No,
Tax_No = dbAccount.Tax_No.ToString(),
Reg_No = dbAccount.Reg_No
//Tarsus_Country = dbAccount.Main_Phone
};
}
var officialDatabaseList = crmAccounts;
foreach (var crmAcc in officialDatabaseList)
{
QueryExpression qe = new QueryExpression();
qe.EntityName = "account";
qe.ColumnSet = new ColumnSet("accountnumber", "new_vatno", "new_registrationnumber");
qe.Criteria.AddCondition("accountnumber", ConditionOperator.In,'list of account numbers go here'
EntityCollection response = service.RetrieveMultiple(qe);
foreach (var acc in response.Entities)
{
if (crmAcc.Account_No == acc.Attributes["accountnumber"].ToString())
{
//acc.Attributes["new_vatno"] = crmAcc.VAT_No.ToString();
acc.Attributes["new_registrationnumber"] = crmAcc.Reg_No.ToString();
service.Update(acc);
}
}
}
My code to use the function for updating is here and it works also
[HttpPost]
public bool SaveDefCompny(DefCompanyDTO DefCmpny)
{
using (RPDBEntities db = new RPDBEntities())
{
using (TransactionScope trans = new TransactionScope())
{
//the problem is here incase of saving
var UpdateDefCmpnyId = (from CmpnyId in db.DefCompanies
where CmpnyId.Id == DefCmpny.Id
select CmpnyId).First();
List<DefCompany> list = new List<DefCompany>();
list.Add(UpdateDefCmpnyId);
try
{
foreach (DefCompany DefCmpny1 in list)
{
DefCmpny1.Id = DefCmpny1.Id;
DefCmpny1.ShortName = DefCmpny.ShortName;
DefCmpny1.FullName = DefCmpny.FullName;
DefCmpny1.ContactPerson = DefCmpny.ContactPerson;
DefCmpny1.Address1 = DefCmpny.Address1;
DefCmpny1.CompanyCity = DefCmpny.CompanyCity;
DefCmpny1.CompanyState = DefCmpny.CompanyState;
DefCmpny1.CompanyCountry = DefCmpny.CompanyCountry;
DefCmpny1.ZipPostCode = DefCmpny.ZipPostCode;
DefCmpny1.TelArea = DefCmpny.TelArea;
DefCmpny1.CurrentCurrencyCode = DefCmpny.CurrentCurrencyCode;
db.SaveChanges();
trans.Complete();
}
}
catch (Exception ex)
{
}
}
return false;
}
}
when I try to save instead of updating the line of code
var UpdateDefCmpnyId = (from CmpnyId in db.DefCompanies
where CmpnyId.Id == DefCmpny.Id
select CmpnyId).First();
gives null value and hence saving fails because record is new and not present in database so how to handle null in case of saving how to use try catch so that when value is null it proceed to saving code that add
How about something along these lines:
var UpdateDefCmpnyId = (from CmpnyId in db.DefCompanies
where CmpnyId.Id == DefCmpny.Id
select CmpnyId).FirstOrDefault();
if(UpdateDefCmpnyId == null)
{
//insert
//(handle the id however you need to for insert. depending on your setup, you might be able to leave it empty and let the database put it in for you)
}
else
{
//update
//set the id as you do in the question
}
I am LINQ to input information from a Database. I have my try.catch block set up to catch these exceptions. However I believe I ran into a sore spot where I am attempting to see what the message is but it just bypass printing the message to me and goes directly to error page. Here is an example of the code I have so far. I would love to get some input on why this seems to be acting so strange.
private void CreateEntry()
{
var date = DateTime.Today;
var version = (from v in house.StayLateVersions
where v.Active
select v).FirstOrDefault();
if (version == null)
{
throw new NullReferenceException();
}
//Try to create an entry for the database. Upon failure, sends the exception to ThrowDbError();
try
{
ResidenceHallInspection rhi = new ResidenceHallInspection();
rhi.versionId = version.id;
rhi.submitDate = DateTime.Now;
rhi.CheckInOrOut = ddlCheck.SelectedItem.Text;
rhi.Id = txtId.Text;
rhi.FirstName = txtFirstName.Text;
rhi.MiddleName = txtMiddleName.Text;
rhi.LastName = txtLastName.Text;
rhi.Walls = chbxWalls.SelectedItem.Text;
rhi.Windows = chbxWindows.SelectedItem.Text;
rhi.Blinds = chbxBlinds.SelectedItem.Text;
rhi.Couch = chbxCouch.SelectedItem.Text;
rhi.CommonRoomCouch = chbxCRCouch.SelectedItem.Text;
rhi.CommonRoomChair = chbxCRChair.SelectedItem.Text;
rhi.Doors = chbxDoors.SelectedItem.Text;
rhi.Carpet = chbxCarpet.SelectedItem.Text;
rhi.Ceiling = chbxCeiling.SelectedItem.Text;
rhi.CommonRoomCounter = chbxCRCounter.SelectedItem.Text;
rhi.Cabinet = chbxCabinet.SelectedItem.Text;
rhi.Phone = chbxPhone.SelectedItem.Text;
rhi.Bed = chbxBed.SelectedItem.Text;
rhi.Desk = chbxDesk.SelectedItem.Text;
rhi.DeskChairs = chbxDeskChair.SelectedItem.Text;
rhi.Tub = chbxTub.SelectedItem.Text;
rhi.Vanity = chbxVanity.SelectedItem.Text;
rhi.Notes = txtNotes.Text;
rhi.Building = txtResHall.Text;
rhi.ApartmentNumber = txtSuitNo.Text;
rhi.BedSpace = txtBedSpace.Text;
house.AddToResidenceHallInspections(rhi);
house.SaveChanges();
}
catch (Exception oe)
{
ThrowDbError(oe);
Response.Write(oe.InnerException);
}
}
/*=================================================*/
/*Possible Errors */
/*=================================================*/
private void ThrowDbError(Exception oe)
{
Response.Write(oe.Source);
house.Dispose();
Session.Contents.Add("FormException", oe);
Response.Redirect("/Database-Error/", true);
}
The most likely reason for that to happen is that you are running the database version query outside the try/catch block. Any exception in this db access code will not be handled by the code you have shown above.
Try extending your try block to also include the db access code:
var version = (from v in house.StayLateVersions
where v.Active
select v).FirstOrDefault();
if (version == null)
{
throw new NullReferenceException();
}
and see if this time the error is caught.