I'm using a WCF-webservice and Linq-To-SQL to insert a new record.
However, in the webservice i'm setting two fields, CreatedBy and Created, but even if i use ref parameter(as suggested on MSDN) the changes are not reflected at the client. So when i debug the service the properties are set and the record is inserted correctly, but at the calling method the object's properties are still unset.
This will cause problems later, for example if i'll try to delete it i'll get following exception at db.SubmitChanges() since these columns are non-null:
System.Data.SqlTypes.SqlTypeException: SqlDateTime overflow. Must be
between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
Here's the insert method at the client(winforms application):
private void Add_Status()
{
using (var db = new ERP_ServiceClient())
{
var status = new Erp_ServiceReference.Status();
status.Name = this.txtStatusNameAdd.Text;
db.InsertStatus(status, this.IdUser);
statusBindingSource.Add(status);
}
this.txtStatusNameAdd.Text = "";
this.txtStatusNameAdd.Select();
}
This is the webservice method:
public void InsertStatus(ref Status status, int userID)
{
using (var db = new ERPDataContext())
{
status.CreatedBy = userID;
status.Created = DateTime.Now;
db.Status.InsertOnSubmit(status);
db.SubmitChanges();
}
}
What am i doing wrong? My wcf,winforms and linq-to-sql skills are rusty(that's why i've chosen them).
You can't pass by reference in a web service. You can return the value.
public Status InsertStatus(Status status, int userID)
{
using (var db = new ERPDataContext())
{
status.CreatedBy = userID;
status.Created = DateTime.Now;
db.Status.InsertOnSubmit(status);
db.SubmitChanges();
return status;
}
}
private void Add_Status()
{
using (var db = new ERP_ServiceClient())
{
var status = new Erp_ServiceReference.Status();
status.Name = this.txtStatusNameAdd.Text;
status = db.InsertStatus(status, this.IdUser);
statusBindingSource.Add(status);
}
this.txtStatusNameAdd.Text = "";
this.txtStatusNameAdd.Select();
}
Related
I am working with BigQuery. I create a DataSet and I want to define access rights with C# language.
It's not clear to me how to do it.
In GOOGLE web page https://cloud.google.com/bigquery/docs/dataset-access-controls is explained how to do it with some example for Java and Pyton (see below), but no example is provided for c#.
example in pyton:
dataset = client.get_dataset(dataset_id) # Make an API request.
entry = bigquery.AccessEntry(
role="READER",
entity_type="userByEmail",
entity_id="sample.bigquery.dev#gmail.com",
)
entries = list(dataset.access_entries)
entries.append(entry)
dataset.access_entries = entries
dataset = client.update_dataset(dataset, ["access_entries"]) # Make an API request.
full_dataset_id = "{}.{}".format(dataset.project, dataset.dataset_id)
Can anybody help please?
It's probably best to use the BigQueryDataset.Patch method, from the Google.Cloud.BigQuery.V2 package:
// Fetch the existing dataset
var client = BigQueryClient.Create(projectId);
var dataset = client.GetDataset(datasetId);
var accessList = dataset.Resource.Access ?? new List<AccessData>();
accessList.Add(new AccessData
{
Role = "Reader",
UserByEmail = "sample.bigquery.dev#gmail.com"
});
var patchedResource = new Dataset { Access = accessList };
// Push the changes back up to BigQuery
dataset.Patch(patchedResource, matchETag: true);
As an alternative, you can use Update to update the replace the dataset resource completely:
// Fetch the existing dataset
var client = BigQueryClient.Create(projectId);
var dataset = client.GetDataset(datasetId);
// Modify it in memory
var resource = dataset.Resource;
if (resource.Access is null)
{
// If there's no access list yet, create one.
resource.Access = new List<AccessData>();
}
var newAccess = new AccessData
{
Role = "Reader",
UserByEmail = "sample.bigquery.dev#gmail.com"
};
resource.Access.Add(newAccess);
// Push the changes back up to BigQuery
dataset.Update();
At the and I managed to make it work.
I used the same solution suggested by Jon Skeet, using the Patch method.
I attach my code here by.
public static bool GrantDatasetAccess(string dataSetId, bool online, string role, string email,
string bigQueryJsonPath, string bigQueryScope, string projectId, clsLog log)
{
try
{
BigQueryClient client = GetBigQueryClient(online, bigQueryJsonPath, bigQueryScope, projectId);
BigQueryDataset dataset = GetDataSet(online, dataSetId, bigQueryJsonPath, bigQueryScope, projectId, log);
List<AccessData> accessList = new List<AccessData>();
var accessData = new AccessData()
{
Role = role,
GroupByEmail = null,
UserByEmail = email,
SpecialGroup = null,
IamMember = null,
Domain = null,
View = null
};
accessList.Add(accessData);
dataset.Resource.Access = accessList;
dataset.Patch(dataset.Resource, true);
}
catch (Exception e)
{
log.ManageError("Error GetDataSet: {0}\nError: {1}", dataSetId, string.Concat(e.Message, "\n", e.StackTrace));
}
return true;
}
Having problems with accessing what is inside my list in a wpf application of a mafia game I am creating.
Basically I read from SQL Server 2016, then add it to my user collection list. Later when I use my list in a display, they all are there.
However the moment I use a foreach to loop through it to set a temp user equal to a found username, it only finds hard coded users and not ones added using the data read from SQL Server. Need help.
SQL Server read code:
using (connect = new SqlConnection(connetionString))
{
connect.Open();
string readString = "select * from Users";
SqlCommand readCommand = new SqlCommand(readString, connect);
using (SqlDataReader dataRead = readCommand.ExecuteReader())
{
if (dataRead != null)
{
while (dataRead.Read())
{
tempEmail = dataRead["Email"].ToString();
tempName = dataRead["Name"].ToString();
UserCollection.addUser(tempEmail, tempName);
}
}
}
connect.Close();
}
UserCollection relevant parts
private static List<User> UserList = new List<User>();
// add a user
public static void addUser(string email, string name)
{
UserList.Add(new User(email, name, 0, "unset", false, false, false, false, false, false,
false, "", false, false, false, 0, 0));
}
//return list of users for use elsewhere
public static List<User> ReturnUserList()
{
return UserList;
}
Use of a list to set tempPlayer in a wpf window
PlayersList = UserCollection.ReturnUserList();
// tempPlayer = UserCollection.ReturnAUser(sessionUser);
foreach (var element in PlayersList)
{
if (element.UserName == sessionUser)
{
tempPlayer = element;
}
}
Example of code where the list works.
// set listing of current players
ListOfPlayers = UserCollection.ReturnUserList();
var tempList = from player in ListOfPlayers
where player.UserBlocked == false
select new
{
Name = player.UserName,
Email = player.UserEmail,
};
this.PlayerListBox.ItemsSource = tempList;
hard coded User add that works fine and can be found by foreach statement from my app.xaml.cs
UserCollection.addUser("g", "Tom");
Firstly, is there a reason why you need a static method to add users to a collection? Even if you need access to the list via a static accessor, you are better having a static property on the same class which you're using to read the DB
The following snippet should hopefully be of some help.
public class UserManagement {
//Static property
private static List<User> _users;
public static List<User> Users {
get {
if (_users == null) {
_user = new List<User>();
}
return _users;
}
set { }
}
//Static load method must be called before accessing Users
public static void LoadDBUsers() {
using (SqlConnection connection = new SqlConnection(connetionString)) {
connection.Open();
string readString = "select * from Users";
using (SqlCommand command = new SqlCommand(readString, connection)) {
using (SqlDataReader reader = command.ExecuteReader()) {
while (reader.Read()) {
String tempEmail = reader["Email"].ToString();
String tempName = reader["Name"].ToString();
User user = new User(tempEmail, tempName, 0, "unset", false, false, false, false, false, false, false, "", false, false, false, 0, 0));
users.Add(user);
}
}
}
}
}
}
To use from another class :
UserManagement.LoadDBUsers();
var dbUsers = UserManagement.Users;
If you have another list of users (say from a file), you could add a loader method to your class which will handle that for you.
If at some point you need to clear down the list of users, you can simply set it to a new instance...
UserManagement.Users = new List<User>();
A slightly better way to do this would be to remove the static property Users first, change the method definition to return a List<User> from the LoadDBUsers method - eg.
public static List<User> LoadDBUsers() {
List<User> Users = new List<User>();
//Handle the database logic as in the previous example..
//Then at the end of the method..
return Users;
}
and call as follows
List<User> dbUsers = UserManagement.LoadDBUsers();
Using the latter approach, you don't need to worry about multiple locations in your code maintaining a static property. Just call and assign it to a variable.
It also has the advantage that you will always get the most current list of users from the DB without having to clear down and reload the list before you access it from the static property.
An added advantage of not using a global static property is that it can avoid potential memory issues. Static properties can be difficult to dispose by the garbage collector if a reference to them is held open.
With instance variables, it's quite obvious when one goes out of scope and is not referenced anymore, but with static variables, the reference is sometimes not disposed until the program ends.
In many cases, this isn't an issue, but in larger systems it can be a pain to debug.
tempEmail = dataRead["Email"].ToString();
tempName = dataRead["Name"].ToString();
tempEmail,tempName you are declare above on
using (connect = new SqlConnection(connetionString))
the tempEmail and tempName are reference type so, if loop it's first record add after second time loop tempName and tempEmail values update also previously added so,because it's also pointing same memory. so the data's are duplicate record list so, the users cannot add in user properly.
so, you can change your code
var tempEmail = dataRead["Email"].ToString();
var tempName = dataRead["Name"].ToString();
and before tempEmail,tempName remove the declaration before using statement.
I Hope this is Helpful for you.
I believe your while loop was causing the issue. Since "using" was in effect, the global, assumed, variables "tempEmail" & "tempName" remained null. I tested the code using MySql on my end and this solution was effective.
private List<User> PlayersList;
public Tester()
{
using (SqlConnection connect = new SqlConnection(connectionString))
{
connect.Open();
string readString = "select * from user";
SqlCommand readCommand = new SqlCommand(readString, connect);
using (SqlDataReader dataRead = readCommand.ExecuteReader())
{
if (dataRead != null)
{
while (dataRead.Read())
{
string tempEmail = dataRead["Email"].ToString();
string tempName = dataRead["Name"].ToString();
UserCollection.addUser(tempEmail, tempName);
}
}
}
connect.Close();
}
PlayersList = UserCollection.ReturnUserList();
}
public class User
{
public string email;
public string name;
// A constructor that takes parameter to set the properties
public User(string e, string n)
{
email = e;
name = n;
}
}
public static class UserCollection
{
private static List<User> UserList = new List<User>();
// add a user
public static void addUser(string email, string name)
{
UserList.Add(new User(email, name));
}
//return list of users for use elsewhere
public static List<User> ReturnUserList()
{
return UserList;
}
}
This is the area of concern.
while (dataRead.Read())
{
//Set local variable during while loop
string tempEmail = dataRead["Email"].ToString();
string tempName = dataRead["Name"].ToString();
UserCollection.addUser(tempEmail, tempName);
}
I have WCF Data Service application. The back-end database is Ingress and it uses nHibernate.
I am trying to fetch and update records from one of the tables. Its structure is given here under:
First three highlighted columns make primary key.
In my client application I am querying the data like below:
private void LoadItemDetails(string itemCode, int commentDate)
{
using(var dc = new MyDataContext(new Uri("http://myservice.myserver.com/Dev/com.OData/IngressData.svc")))
{
var itemDetails = dc
.ItemLineDetails
.Where(d => d.ItemCode.Equals(itemCode) &&
ld.CommentDate == commentDate);
ObsItemLineDetails = new ObservableCollection<ItemLineDets>();
}
}
Then I update and save the data as shown below:
private void SaveItemDetails()
{
using(var dc = new MyDataContext(new Uri("http://myservice.myserver.com/Dev/com.OData/IngressData.svc")))
{
foreach(var itemLine in ObsItemLineDetails )
{
var today = DateTime.Today.AddSeconds(-1);
var newCommentDate = (Int32)(today.Subtract(new DateTime(1970, 1, 1,0,0,0))).TotalSeconds;
var itemDetail = dc.ItemLineDetails.Where(d => d.ItemCode.Equals(itemLine.ItemCode) &&
d.LineId == itemLine.LineId &&
d.SearchDate == itemLine.SearchDate).FirstOrDefault();
if (itemDetail != null)
{
itemDetail.CommentDate = newCommentDate;
itemDetail.Comments = GetAutoComment();
dc.UpdateObject(itemDetail);
}
}
dc.SaveChanges();
}
}
It raises an exception on the last line when SaveChanges is being called. Following is the IIS server log entry.
15:52:42.7823 Trace 20 com.OData.DataServiceBase`1 Received: http://myservice.myserver.com/Dev/com.OData/IngressData.svc/ItemLineDetails(ItemCode='001/152/0101',LineId=3,SearchDate=11070945856)
15:52:42.7823 Error 20 com.OData.DataServiceBase`1 Bad Request - Error in query syntax.
at System.Data.Services.RequestUriProcessor.ParsePath(Uri absoluteRequestUri, IDataService service)
at System.Data.Services.RequestUriProcessor.ProcessRequestUri(Uri absoluteRequestUri, IDataService service, Boolean internalQuery)
at System.Data.Services.DataService`1.HandleRequest() at System.Data.Services.RequestUriProcessor.ParsePath(Uri absoluteRequestUri, IDataService service)
at System.Data.Services.RequestUriProcessor.ProcessRequestUri(Uri absoluteRequestUri, IDataService service, Boolean internalQuery)
at System.Data.Services.DataService`1.HandleRequest()
I think its probably the forward slashes in my ITEM_CODE field causing this problem.
If that's the case, is there any workaround for this.
try to add using on DataContext in the function instead of a global context object
like below
private void SaveItemDetails()
{
using(context dc = new context())
{
foreach(var itemLine in ObsItemLineDetails )
{
var today = DateTime.Today.AddSeconds(-1);
var newCommentDate = (Int32)(today.Subtract(new DateTime(1970, 1, 1,0,0,0))).TotalSeconds;
var itemDetail = dc.ItemLineDetails.Where(d => d.ItemCode.Equals(itemLine.ItemCode) &&
d.LineId == itemLine.LineId &&
d.SearchDate == itemLine.SearchDate).FirstOrDefault();
if (itemDetail != null)
{
itemDetail.CommentDate = newCommentDate;
itemDetail.Comments = GetAutoComment();
dc.UpdateObject(itemDetail);
}
}
dc.SaveChanges();
}
}
i'm trying to add multiple textbox values to database it is working on just single textbox row but now working when i'm adding multiple rows of textboxes. i'm sharing what i have done so far.
Action Method:
public async Task<ActionResult> Create(FormCollection values)
{
var customer = new Customer();
var model = new TicketViewModel();
TryUpdateModel(model.TicketDetail);
try
{
foreach (var ticket in model.Tickets)
{
ticket.Date = DateTime.Now;
ticket.ProcessId = DateTime.Now.Ticks.ToString().Substring(12, 6);
ticket.CreationMethod = "Manual";
ticket.isCustomer = User.IsInRole("Customer") ? true : false;
ticket.Total = 0;
ticket.Email = model.TicketDetail.Ticket.Email;
customer.City = "Not Specified";
customer.Country = "Not SPecified";
customer.Image = "~/Images/nopic.jpg";
customer.Password = System.Web.Security.Membership.GeneratePassword(11, 3);
customer.IsActive = true;
customer.CreationMethod = "Manual";
customer.DateAdded = DateTime.Now;
customer.Email = ticket.Email;
customer.FirstMidName = string.IsNullOrEmpty(ticket.FullName) ? "Not Specified" : ticket.FullName;
customer.LastName = "Not Specified";
customer.Salutation = "Not Specified";
customer.UserName = DateTime.Now.Ticks.ToString().Substring(3, 9);
//ticket detail
var abcd = values["abcd"].ToString();
var getID = await db.Parts.Where(c => c.PartNumber == abcd)
.FirstOrDefaultAsync();
model.TicketDetail.GenericOrderId = ticket.GenericOrderId;
model.TicketDetail.PersonID = customer.PersonID;
model.TicketDetail.Status = "New";
model.TicketDetail.PartId = getID.PartId;
model.TicketDetail.Ticket.Date = DateTime.Now;
}
try
{
// db.Tickets.Add(ticket);
db.Customers.Add(customer);
db.TicketDetails.Add(model.TicketDetail);
}
catch (Exception ex)
{
ViewBag.PartId = new SelectList(db.Parts.Take(5), "PartId", "Name");
ModelState.AddModelError("", string.Format(ex.Message + "\n" + ex.InnerException));
return View(model.TicketDetail);
}
// Save all changes
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
catch(Exception ex)
{
ModelState.AddModelError("", String.Format(ex.Message + "\n" + ex.InnerException));
//Invalid - redisplay with errors
return View(model.TicketDetail);
}
}
ViewModel:
public class TicketViewModel
{
public TicketViewModel()
{
TicketDetails = new List<TicketDetail>();
TicketDetail = new TicketDetail();
Ticket = new Ticket();
Tickets = new List<Ticket>();
}
public virtual Ticket Ticket { get; set; }
public virtual IEnumerable<Ticket> Tickets { get; set; }
public virtual TicketDetail TicketDetail { get; set; }
public virtual IEnumerable<TicketDetail> TicketDetails { get; set; }
}
it is also giving error on this "TryUpdateModel(model.TicketDetail);" the error is value cannot be null, please guide me i'm stuck here i have searched internet but couldn't found any appropriate solution. i want to add multiple records
First all properties of your TicketViewModel class have to be instantiated.
To add multiple records (multiple Insert) you could use a StringBuilder and append the insert statements to it. You then have one big query string to be executed on your database.
If using values this is also a valid way:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
And loading the data to be inserted directly from a file is even faster.
Edit
(after down voting for no reason)
Because some people act like they know it all:
SQL injections are indeed a serious problem when dealing with Database access. That's no secret at all. A common technique to prevent the SQL query from being 'highjacked' you simply use the SQLCommand.Parameters property which is used to map each value individually to the statement to separate the query statement from the data (values) this way. It's now impossible to inject or manipulate statements whithout breaking them. And server side validation is standard to obtain maximum security as well as escaping special input characters and avoiding the use of privilegs with no or low restrictions.
This is NOT a wrong answer.
I am programming a client program that calls a webmethod but when I get the return data there are missing values on some of the fields and objects.
The webmethod in turn is calling a WCF method and in the WCF method the return data is fine. But when it is passing to the webservice the return data is missing.
Is there any way to fix this problem?
This is my client code calling the webservice:
ReLocationDoc query = new ReLocationDoc();
query.PerformerSiteId = 1;
query.PerformerUserId = 1;
query.FromStatus = 10;
query.ToStatus = 200;
ReLocationDoc doc = new ReLocationDoc();
ServiceReference1.QPSoapClient service = new QPSoapClient();
try {
service.GetRelocationAssignment(query, out doc);
string test = doc.Assignment.Id.ToString();
} catch(Exception ex) {
MessageBox.Show(ex.Message);
}
The webmethod code is here:
[WebMethod]
return m_reLocationClient.GetRelocationAssignment(query, out reLocationDoc);
}
And at last the WCF code:
public ReLocationResult GetRelocationAssignment(ReLocationDoc query, out ReLocationDoc reLocationDoc) {
try {
LOGGER.Trace("Enter GetRelocationAssignment().");
ReLocationResult result = reLocationCompactServiceClient.GetRelocationAssignment(out reLocationDoc, query);
if(reLocationDoc.Assignment == null || reLocationDoc.Assignment.CurrentStatus == STATUS_FINISHED) {
ReLocationDoc newQuery = new ReLocationDoc();
newQuery.Assignment = new AssignmentDoc();
newQuery.Assignment.EAN = DateTime.Today.ToString();
newQuery.PerformerSiteId = QPSITE;
newQuery.PerformerUserId = QPUSER;
reLocationDoc.AssignmentStatus = m_settings.ReadyStatus; ;
result = reLocationCompactServiceClient.CreateReLocationAssignment(out reLocationDoc, newQuery);
}
return result;
} finally {
LOGGER.Trace("Exit GetRelocationAssignment().");
}
}
The GetRelocationAssignment:
public ReLocationResult GetRelocationAssignment(ReLocationDoc query, out ReLocationDoc reLocationDoc) {
try {
LOGGER.Trace("Enter GetRelocationAssignment().");
ReLocationDoc doc = new ReLocationDoc();
ReLocationResult result = new ReLocationResult();
new Database(Connection).Execute(delegate(DBDataContext db) {
User user = GetVerifiedUser(db, query, MODULE_ID);
SiteModule siteModule = SiteModule.Get(db, query.PerformerSiteId, MODULE_ID);
Status status = Status.Get(db, query.FromStatus, query.ToStatus, 0);
Status startStatus = Status.Get(db, query.FromStatus, 0);
Status endStatus = Status.Get(db, query.ToStatus, 0);
IQueryable<Assignment> assignments = Assignment.GetAssignmentsWithEndStatus(db, siteModule, endStatus);
assignments = Assignment.FilterAssignmentStartStatus(assignments, startStatus);
foreach(Assignment assignment in assignments) {
LOGGER.Debug("Handling assignment: " + assignment.Id);
result.Status = true;
AssignmentDoc assignmentDoc = FillAssignmentDoc(assignment);
//ReLocationDoc doc = new ReLocationDoc();
AssignmentStatus sts = assignment.AssignmentStatus.OrderByDescending(ass => ass.Id).First();
assignmentDoc.CurrentStatus = sts.Status.Zone;
Status currentStatus = sts.Status;
IList<Item> items = assignment.Items.ToList();
IList<ItemDoc> itemDocs = new List<ItemDoc>();
foreach(Item item in items) {
ItemDoc itemDoc = FillItemDoc(item);
ItemDetail itemDetail;
if(ItemDetail.TryGet(db, item.Id, out itemDetail)) {
ItemDetailDoc itemDetailDoc = FillItemDetailDoc(itemDetail);
itemDoc.Details = new ItemDetailDoc[1];
Event eEvent = null;
if(Event.GetEvent(db, itemDetail, currentStatus, out eEvent)) {
EventDoc eventDoc = FillEventDoc(eEvent);
itemDetailDoc.Events = new EventDoc[1];
if(eEvent.LocationId.HasValue) {
Location location = null;
if(Location.TryGet(db, eEvent.LocationId.Value, out location)) {
eventDoc.Location = new LocationDoc();
eventDoc.Location = FillLocationDoc(location, db);
}
}
itemDetailDoc.Events[0] = eventDoc;
}
itemDoc.Details[0] = itemDetailDoc;
}
itemDocs.Add(itemDoc);
}
assignmentDoc.Items = itemDocs.ToArray();
doc.Assignment = assignmentDoc;
}
}, delegate(Exception e) {
result.Message = e.Message;
});
reLocationDoc = doc;
return result;
} finally {
LOGGER.Trace("Exit GetRelocationAssignment().");
}
}
In all this code the return data is fine. It is loosing data only when passing to the webmetod.
Enter code here.
Also, the ordering of the XML tags in the message makes difference - I had a similar problem about maybe two years ago, and in that case parameter values were dissappearing during transmission because the sending part ordered the tags differently than what was defined in the schema.
Make surethe XML tags are being accessed with the same casing at either end. if the casing is not the same then the value won't be read.
You should check it all message are sending back from your webservice. Call your webservice manually and check its response.
If all data is there, probably your webservice reference is outdated; update it by right-clicking your webservice reference and choose "Update"
If your data don't came back, your problem is probably related to webservice code. You should check your serialization code (if any) again, and make sure all returned types are [Serializable]. You should check if all return types are public as it's mandatory for serialization.
As noted per John Saunders, [Serializable] isn't used by XmlSerializer.