Implementing queue in c# - c#

I am developing a c# application, in which the server gets requests from many clients at a time. Each client also gets their data from different databases. In this situation sometimes data leakage is happening, means clients get data from an incorrect database. Say for example client1 should get data from db1 and client2 gets data from db2. Instead they get data from opposite databases; client1 gets from db2 and client2 gets from db1.
I am adding the code below where it collects the data.
public string List()
{
Response.ContentType = ContentType.Xml;
try
{
ThingzFilter filter = null;
Dictionary<string, string> parameters = new Dictionary<string, string>();
if (Id!="")
{
// get parameters from http request
foreach (HttpInputItem param in Request.Param)
parameters.Add(param.Name, param.Value);
setServerURLs();
//Request.Clear();
if (Request.QueryString["lang"].Value != null)
{
ThingzDB.TzThing.get_language = Request.QueryString["lang"].Value.ToString();
}
else
{
ThingzDB.TzThing.get_language = SessionDatabase.DefaultLanguage;
}
}
ThingzDatabase db = SessionDatabase;
langStr = db.Language;
// this is run if there was no ID supplied
// which means we want all items of all types
if (Id == "")
{
if (Request.AcceptTypes == null)
{
//TypeController.session_id = Request.QueryString["sessionid"].Value;
jobs.Add(Request.QueryString["sessionid"].Value);
if (nextJobPos > jobs.Count - 1)
return "";
else
{
TypeController.session_id = jobs[nextJobPos];
nextJobPos++;
langStr = SessionDatabase.Language;
}
filter = new AllThingzFilter(SessionDatabase, parameters, langStr);
TypeController.session_id = "";
filter.Execute();
}
In this server is console application and clients are windows where the site names , means the databse names are mentioned.
Please give me a solution to overcome this issue.

Without precisely knowing how SessionDatabase is scoped (from the name it seems to be a session variable) or whether it's implementation is a property that does some kind of complex logic, I would guess you have two problems:
Storing the value at the wrong scope with multiple clients accessing it
Using db and SessionDatabase interchangeably in your code.
For the latter, I would suggest db = SessionDatabase once at the top of the code (making sure that SessionDatabase was the right thing for that client, and then using db for the rest of the method.

Related

NetSuite SuiteTalk: SavedSearch for "Deleted Record" Type

How does one get the results of a "Saved Search" of Type "Deleted Record" in NetSuite? Other search types are obvious(CustomerSearchAdvanced, ItemSearchAdvanced, etc...) but this one seems to have no reference online, just documentation around deleting records, not running saved searches on them.
Update 1
I should clarify a little bit more what I'm trying to do. In NetSuite you can run(and Save) Saved Search's on the record type "Deleted Record", I believe you are able to access at least 5 columns(excluding user defined ones) through this process from the web interface:
Date Deleted
Deleted By
Context
Record Type
Name
You are also able to setup search criteria as part of the "Saved Search". I would like to access a series of these "Saved Search's" already present in my system utilizing their already setup search criteria and retrieving data from all 5 of their displayed columns.
The Deleted Record record isn't supported in SuiteTalk as of version 2016_2 which means you can't run a Saved Search and pull down the results.
This is not uncommon when integrating with NetSuite. :(
What I've always done in these situations is create a RESTlet (NetSuite's wannabe RESTful API framework) SuiteScript that will run the search (or do whatever is possible with SuiteScript and not possible with SuiteTalk) and return the results.
From the documentation:
You can deploy server-side scripts that interact with NetSuite data
following RESTful principles. RESTlets extend the SuiteScript API to
allow custom integrations with NetSuite. Some benefits of using
RESTlets include the ability to:
Find opportunities to enhance usability and performance, by
implementing a RESTful integration that is more lightweight and
flexible than SOAP-based web services. Support stateless communication
between client and server. Control client and server implementation.
Use built-in authentication based on token or user credentials in the
HTTP header. Develop mobile clients on platforms such as iPhone and
Android. Integrate external Web-based applications such as Gmail or
Google Apps. Create backends for Suitelet-based user interfaces.
RESTlets offer ease of adoption for developers familiar with
SuiteScript and support more behaviors than NetSuite's SOAP-based web
services, which are limited to those defined as SuiteTalk operations.
RESTlets are also more secure than Suitelets, which are made available
to users without login. For a more detailed comparison, see RESTlets
vs. Other NetSuite Integration Options.
In your case this would be a near trivial script to create, it would gather the results and return JSON encoded (easiest) or whatever format you need.
You will likely spend more time getting the Token Based Authentication (TBA) working than you will writing the script.
[Update] Adding some code samples related to what I mentioned in the comments below:
Note that the SuiteTalk proxy object model is frustrating in that it
lacks inheritance that it could make such good use of. So you end with
code like your SafeTypeCastName(). Reflection is one of the best tools
in my toolbox when it comes to working with SuiteTalk proxies. For
example, all *RecordRef types have common fields/props so reflection
saves you type checking all over the place to work with the object you
suspect you have.
public static TType GetProperty<TType>(object record, string propertyID)
{
PropertyInfo pi = record.GetType().GetProperty(propertyID);
return (TType)pi.GetValue(record, null);
}
public static string GetInternalID(Record record)
{
return GetProperty<string>(record, "internalId");
}
public static string GetInternalID(BaseRef recordRef)
{
PropertyInfo pi = recordRef.GetType().GetProperty("internalId");
return (string)pi.GetValue(recordRef, null);
}
public static CustomFieldRef[] GetCustomFieldList(Record record)
{
return GetProperty<CustomFieldRef[]>(record, CustomFieldPropertyName);
}
Credit to #SteveK for both his revised and final answer. I think long term I'm going to have to implement what is suggested, short term I tried implementing his first solution("getDeleted") and I'd like to add some more detail on this in case anyone needs to use this method in the future:
//private NetSuiteService nsService = new DataCenterAwareNetSuiteService("login");
//private TokenPassport createTokenPassport() { ... }
private IEnumerable<DeletedRecord> DeletedRecordSearch()
{
List<DeletedRecord> results = new List<DeletedRecord>();
int totalPages = Int32.MaxValue;
int currentPage = 1;
while (currentPage <= totalPages)
{
//You may need to reauthenticate here
nsService.tokenPassport = createTokenPassport();
var queryResults = nsService.getDeleted(new GetDeletedFilter
{
//Add any filters here...
//Example
/*
deletedDate = new SearchDateField()
{
#operator = SearchDateFieldOperator.after,
operatorSpecified = true,
searchValue = DateTime.Now.AddDays(-49),
searchValueSpecified = true,
predefinedSearchValueSpecified = false,
searchValue2Specified = false
}
*/
}, currentPage);
currentPage++;
totalPages = queryResults.totalPages;
results.AddRange(queryResults.deletedRecordList);
}
return results;
}
private Tuple<string, string> SafeTypeCastName(
Dictionary<string, string> customList,
BaseRef input)
{
if (input.GetType() == typeof(RecordRef)) {
return new Tuple<string, string>(((RecordRef)input).name,
((RecordRef)input).type.ToString());
}
//Not sure why "Last Sales Activity Record" doesn't return a type...
else if (input.GetType() == typeof(CustomRecordRef)) {
return new Tuple<string, string>(((CustomRecordRef)input).name,
customList.ContainsKey(((CustomRecordRef)input).internalId) ?
customList[((CustomRecordRef)input).internalId] :
"Last Sales Activity Record"));
}
else {
return new Tuple<string, string>("", "");
}
}
public Dictionary<string, string> GetListCustomTypeName()
{
//You may need to reauthenticate here
nsService.tokenPassport = createTokenPassport();
return
nsService.search(new CustomListSearch())
.recordList.Select(a => (CustomList)a)
.ToDictionary(a => a.internalId, a => a.name);
}
//Main code starts here
var results = DeletedRecordSearch();
var customList = GetListCustomTypeName();
var demoResults = results.Select(a => new
{
DeletedDate = a.deletedDate,
Type = SafeTypeCastName(customList, a.record).Item2,
Name = SafeTypeCastName(customList, a.record).Item1
}).ToList();
I have to apply all the filters API side, and this only returns three columns:
Date Deleted
Record Type(Not formatted in the same way as the Web UI)
Name

Holding Values in an object for console application C#

I am currently writing an application where I am getting data from the DB and passing it to the object which will later be used to send the data off else where. The issue I am having in testing is that the data doesn't hold in the object as when it is used later, I get null value errors. I know we can store these in sessions, but I also know you can use objects and have done it before at previous jobs, but do not recall what I am missing to maintain the information. Would I need to pass the object(s) from method to method until the job is done?
the first sample here shows where it is prepping the object.
public void FtpInitialize()
{
_LogController.LogToFile(ValidateMessage.BeginInitialization);
//Loading FTPClient object with ClientInfo Object data we got from DataBase. FTPClient object is the object that sends the data.
_LogController.FTPTraceLogToFile();
ClientInfo = _RepositoryController.GetClientInfo(ClientInfo);
if (ClientInfo == null)
ClientInfo.ClientDataExists = false;
else
{
FTPClient.Host = ClientInfo.Host;
FTPClient.Port = ClientInfo.Port;
FTPClient.EncryptionMode = FtpEncryptionMode.Explicit;
FTPClient.Credentials = new NetworkCredential(ClientInfo.UserName, ClientInfo.Password);
FTPClient.DataConnectionType = FtpDataConnectionType.EPSV; //according library documentation, auto passive is broken as of 10/20/2016
FTPClient.EnableThreadSafeDataConnections = ClientInfo.EnableThreadSafeConnection;
FTPClient.DataConnectionConnectTimeout = ClientInfo.DataConnectionTimeout;
FTPClient.DataConnectionReadTimeout = ClientInfo.DataReadTimeout;
FTPClient.ConnectTimeout = ClientInfo.ConnectionTimeout;
FTPClient.ReadTimeout = ClientInfo.ReadTimeout;
FTPClient.SocketPollInterval = ClientInfo.SocketPollInterval;
FTPClient.SocketKeepAlive = ClientInfo.KeepSocketAlive;
FTPClient.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);
_LogController.LogToFile(ValidateMessage.ClientDataLoaded);
ClientInfo.ClientDataExists = true;
}
}
then below when I hit this part, it shows as null
public bool SendData()
{
short errorCount = 0;
using (FTPClient)
{
if (ClientInfo.ClientDataExists)
{
This looks like you are using local variables in your methods. This is why the data "disappears".
For example if you are pulling data from your database you should have some kind of model class and container so that the data can persist until you are done with it.
EX: You have a database that contains information on people (name, dob, etc).
You should have a class that defines person and possibly a List to store said people. You call your database and pull X person objects into your List variable. You then can pass your List into the methods. Note: You can ditch the List (or whatever collection you use) if you are doing it one at a time.
The implementation of this really depends on how you want the objects to persist. If you know you will only pull one person object at a time you can declare var databasePerson from the database. Use the List if you will be pulling more information and then pop off the object when your are down with it.
Hope that helps.

How do I store emails into my SQL server database?

I am trying to store emails into my SQL server database. These emails I got from Exchange Webservices.
I am using entity Framework and made a ADO .Net Data Model.
My Question is how do I make a method(StoreEmail) that stores these emails into my database.
This is my StoreEmail method that I got so far:
It should store my PhishingMails...
public object StoreMail(Model.PhishingMail PhishingMail)
{
using (var phishingMailStorage = new PhishFinderModel())
{
PhishingMail = MailMapper.Map(Model.PhishingMail);
phishingMailStorage.PhishingMails.Add();
phishingMailStorage.SaveChanges();
return PhishingMail;
}
}
In Mailmapper class I set the properties that I want to store, which are Sender, Subject and Body:
public static PhishingMail Map(EmailMessage OutlookMail)
{
PhishingMail readMail = new PhishingMail();
readMail.Sender = OutlookMail.Sender.Address;
readMail.Body = OutlookMail.Body;
return readMail;
}
This is my DB schema
To clarify my question, I already get the list of emails from the exchange server. Now, all I need to do is insert them into the SQL server.
How do I make my StoreEmail method work to do this?
Please don't be harsh I am really new to this. It feels like I am swimming in an ocean of information and I don't know where to look or start. So any suggested tutorials are very welcome.
Thanks!
You're storing PhishingMail, and you're receiving a PhishingMail, so you don't need your mapping step.
Does this not work?
public void StoreMail(Model.PhishingMail PhishingMail)
{
using (var phishingMailStorage = new PhishFinderModel())
{
phishingMailStorage.PhishingMails.Add(PhishingMail);
phishingMailStorage.SaveChanges();
}
}
You don't need to return the mail, either, since the caller already has it (and it's a lot tidier to have a void return if you're not returning a new/different object.
If you actually need to store an EmailMessage, your method should be:
public void StoreMail(EmailMessage emailMessage)
{
var phishingMail = MailMapper.Map(emailMessage);
using (var phishingMailStorage = new PhishFinderModel())
{
phishingMailStorage.PhishingMails.Add(phishingMail);
phishingMailStorage.SaveChanges();
}
}

What is a good way to perform updates with WCF Data Services (Odata)?

I am trying to devise a good way to perform updates to a SQL Server database using WCF Data Services and Entity Framework. The problem I'm having is that it seems overly complex to perform update, delete, and insert operations using the service.
I'll use typical Customer / Invoices scenario to help explain my current approach. I'm using WPF MVVM for the application. My view model contains a customer object that receives updates from the user. When saving, I pass the customer object to the service. The service must then load the customer object, transfer the property values from the updated customer, then perform the save.
Something like this:
public static int SaveProgram(Customer entity)
int returnValue = 0;
// Setup the service Uri
Uri serviceUri = new Uri(Properties.Settings.Default.DataUri);
try
{
// Get the DB context
var context = new DevEntities(serviceUri);
Customer dbCustomer;
if (entity.CustomerId == 0)
{
dbCustomer = new Customer();
context.AddToCustomers(dbCustomer);
}
else
{
dbCustomer = context.Customers.Where(p => p.CustomerId == entity.CustomerId).FirstOrDefault();
}
if (dbCustomer != null)
{
dbCustomer.StatusId = entity.StatusId;
dbCustomer.FirstName = entity.FirstName;
dbCustomer.LastName = entity.LastName;
dbCustomer.Address = entity.Address;
...
}
context.UpdateObject(dbCustomer);
// Submit Changes
DataServiceResponse response = context.SaveChanges(SaveChangesOptions.Batch);
// Check for errors
...
returnValue = response.Count();
}
... Catch exceptions
return returnValue;
}
Is it really necessary to go through all of this? It seems there should be an easier way.
Adding an invoice requires something like this:
var newInvoice = Invoice.CreateInvoice(0, customerId, etc...);
context.AddRelatedObject(dbCustomer, "Invoices", newInvoice);
Having already added a new invoice to the Customer.Invoices collection, this seems cumbersome.
Deleting an invoice is even worse. To delete an invoice I have to compare the invoices collection from the database with that of the passed in entity. If I cannot find a database version of the invoice in the entity.Invoices collection, then I know it should be deleted.
I have the feeling that I must not be approaching this correctly.

Getting a list of all users via Valence

I am trying to get a list of all users in our instance of Desire2Learn using a looping structure through the bookmarks however for some reason it continuously loops and doesn't return. When I debug it it is showing massive amounts of users (far more than we have in the system as shown by the User Management Tool. A portion of my code is here:
public async Task<List<UserData>> GetAllUsers(int pages = 0)
{
//List<UserData> users = new List<UserData>();
HashSet<UserData> users = new HashSet<UserData>();
int pageCount = 0;
bool getMorePages = true;
var response = await Get<PagedResultSet<UserData>>("/d2l/api/lp/1.4/users/");
var qParams = new Dictionary<string, string>();
do
{
qParams["bookmark"] = response.PagingInfo.Bookmark;
//users = users.Concat(response.Items).ToList<UserData>();
users.UnionWith(response.Items);
response = await Get<PagedResultSet<UserData>>("/d2l/api/lp/1.4/users/", qParams);
if (pages != 0)
{
pageCount++;
if (pageCount >= pages)
{
getMorePages = false;
}
}
}
while (response.PagingInfo.HasMoreItems && getMorePages);
return users.ToList();
}
I originally was using the List container that is commented out but just switched to the HashSet to see if I could notice if duplicates where being added.
It's fairly simple, but for whatever reason it's not working. The Get<PagedResultSet<UserData>>() method simply wraps the HTTP request logic. We set the bookmark each time and send it on.
The User Management Tool indicates there are 39,695 users in the system. After running for just a couple of minutes and breaking on the UnionWith in the loop I'm showing that my set has 211,800 users.
What am I missing?
It appears that you’ve encountered a defect in this API. The next course of action is for you to have your institution’s Approved Support Contact open an Incident through the Desire2Learn Helpdesk. Please make mention in the Incident report that Sarah-Beth Bianchi is aware of the issue, and I will work with our Support team to direct this issue appropriately.

Categories