|
Just from a design point of view, are you sure you want to be creating and closing a new pipe every second? If you're going to be up and running for a bit, why deal with the overhead of constantly creating and destroying a pipe?
Also, in your C# code, you should use a using statement on your pipeClient variable. Its lack may be why you seem to be leaking memory due to incomplete cleanup of your pipe.
Be wary of strong drink. It can make you shoot at tax collectors - and miss.
Lazarus Long, "Time Enough For Love" by Robert A. Heinlein
|
|
|
|
|
Apologies but this is going to be a "How to" question rather than a technical question. I am very new to C# and using Json. I have a CSV file as follows:
Edit - I did manage to find some code here - https:
Time Control_Code Metric Organisation Value DateTime
2018-10-21T00:08:03 JKX 3721 AD450 20 2018-10-21T00:08:00
2018-10-21T00:08:03 BHY 1234 HG650 88 2018-10-21T00:08:00
I need to produce multiple JSON output files from that csv in the following format example:
{
"Time":"2018-10-21T00:08:03",
"Control_Code": "JKX",
"metrics": [
{
"Metric": 3721,
"Organisation":"AD450",
"Value": 20,
"Datetime":"2018-10-21T00:08:00"
},
{
"Metric": 1234,
"Organisation":"HG650",
"value": 88,
"datetime":"2018-10-21T00:08:00"
}
]
}
Now the extra problematic part on top of this is that there is a requirement where only one Control_Code may be used per Json.
Each Json generated must contain a single Control_Code and all related metric values in the metrics array. So the csv will need to be scanned for each different Control_Code and then produce an output for that specific Control_Code and then do the same for any subsequent Control_Codes.
So for example a different Json would be produced with a different Control_Code (from the same csv file) - Example (notice different Control_Code other values will of course change as well, but just providing an example).
{
"Time":"2018-10-21T00:08:03",
"Control_Code": "BHY",
"metrics": [
{
"Metric": 3721,
"Organisation":"AD450",
"Value": 20,
"Datetime":"2018-10-21T00:08:00"
},
{
"Metric": 1234,
"Organisation":"HG650",
"value": 88,
"datetime":"2018-10-21T00:08:00"
}
]
}
Thanks for any advice/information in advance.
|
|
|
|
|
Concentrate on reading the CSV first - I use A Fast CSV Reader[^] - it does all the donkey work for you and can load it into a DataTable very easily.
When you have that, create the appropriate C# classes to hold your expected data - running your JSON data sample through Convert JSON to C# Classes Online - Json2CSharp Toolkit[^] gave these so that'll be a good place to start:
public class Metric
{
public int Metric { get; set; }
public string Organisation { get; set; }
public int Value { get; set; }
public DateTime Datetime { get; set; }
public int? value { get; set; }
public DateTime? datetime { get; set; }
}
public class Root
{
public DateTime Time { get; set; }
public string Control_Code { get; set; }
public List<Metric> metrics { get; set; }
}
Then process the table data to fill out your classes. When you have them, use Json.NET - Newtonsoft[^] to produce the JSON string - you can do what you like with it from there.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Steps
1. Determine how to parse the CSV correctly
1.a. Load it into a flat (list) data structure.
2. Sort it
2.a Determine the appropriate collection where the control code is the primary key.
2.b Iterate through 1.a. If the control code already exists, add record. If it does not exist, create it, then add it.
3. Determine how to create appropriate json. (NOT from the above, but rather just putting it out with fake data.)
3.a Learn how to write a file
3.b Learn how to write a json format.
4. Iterate through 2.a, feed into 3, to product file.
|
|
|
|
|
Your design is flawed; it doesn't reflect the data; and results in a redundant data structure.
The "control code" is at the metric level; where "Time" is the key of the "root".
From there you can create (other) "object graphs" (more easily).
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
That's the problem with CSV: it's flat data store with no hierarchic structure - which always leads to redundant duplication as the only way to build a "proper" structure when the flat data is processed.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I'll accept whatever CSV has to offer under the circumstances (e.g. Excel -> csv), but that doesn't mean propagating the "bad design" in the ETL phase ... one can always go back to the bad design after that.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Gerry Schmitz wrote: Your design is flawed;
Good catch.
That would need to be resolved before anything can proceed.
|
|
|
|
|
I have an ItemObservableCollection called _MyChildren with a collection of clsChild. I am trying to get nonfictions when a clsChild.name string is changed.
Error I am getting on MyChildren.ItemPropertyChanged:
Severity Code Description Project File Line Suppression State
Error CS1661 Cannot convert anonymous method to type 'EventHandler<ItemPropertyChangedEventArgs<clsChild>>' because the parameter types do not match the delegate parameter types C-Sharp-Tests C:\Users\Jeff\Documents\GitHub\C-Sharp-Tests\C-Sharp-Tests\C-Sharp-Tests\clsParent.cs 21 Active
clsParent:
using Countdown;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C_Sharp_Tests
{
internal class clsParent : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ItemObservableCollection<clsChild> _MyChildren;
public clsParent()
{
_MyChildren = new ItemObservableCollection<clsChild>();
this._MyChildren.ItemPropertyChanged += delegate (object sender, PropertyChangedEventArgs e)
{
if (string.Equals("IsChanged", e.PropertyName, StringComparison.Ordinal))
{
this.RaisePropertyChanged("IsChanged");
}
};
}
}
}
clsChild:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C_Sharp_Tests
{
internal class clsChild : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string name { get; set; }
}
}
ItemObservableCollection:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Countdown
{
public sealed class ItemObservableCollection<T> : ObservableCollection<T>
where T : INotifyPropertyChanged
{
public event EventHandler<ItemPropertyChangedEventArgs<T>> ItemPropertyChanged;
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
item.PropertyChanged += item_PropertyChanged;
}
protected override void RemoveItem(int index)
{
var item = this[index];
base.RemoveItem(index);
item.PropertyChanged -= item_PropertyChanged;
}
protected override void ClearItems()
{
foreach (var item in this)
{
item.PropertyChanged -= item_PropertyChanged;
}
base.ClearItems();
}
protected override void SetItem(int index, T item)
{
var oldItem = this[index];
oldItem.PropertyChanged -= item_PropertyChanged;
base.SetItem(index, item);
item.PropertyChanged += item_PropertyChanged;
}
private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnItemPropertyChanged((T)sender, e.PropertyName);
}
private void OnItemPropertyChanged(T item, string propertyName)
{
var handler = this.ItemPropertyChanged;
if (handler != null)
{
handler(this, new ItemPropertyChangedEventArgs<T>(item, propertyName));
}
}
}
public sealed class ItemPropertyChangedEventArgs<T> : EventArgs
{
private readonly T _item;
private readonly string _propertyName;
public ItemPropertyChangedEventArgs(T item, string propertyName)
{
_item = item;
_propertyName = propertyName;
}
public T Item
{
get { return _item; }
}
public string PropertyName
{
get { return _propertyName; }
}
}
}
|
|
|
|
|
I don't see why you just didn't stick with ObservableCollection. It's concurrent for read only. You simply "subscribe / unsubscribe". As if you can predict what properties to refresh on the client side.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
I've known about Visual Studio user secrets for a while but haven't used them. And I know that GitHub has secrets, which can be used in repos and I'm sure GH Actions, but again I haven't used them.
That's all going to change very soon. I'd like to use VS user secrets for connection strings, API keys, etc. But when I commit to a GH repo, I'd like the GH action to use the GH secrets saved in that repo on GH. The only thing is, how do I do that? The syntax, I'm sure, isn't the same. How do I do what I want to do?
Rod
|
|
|
|
|
|
Thank you, Richard. I'm reading the document you linked to now. I'm about a third of the way through it. It speaks of ASP.NET Core, which in my case is fine, as this is a new app. However, we have hundreds of custom apps all written using old versions of the .NET Framework. Does that mean that Visual Studio user secrets will not work?
Rod
|
|
|
|
|
Rod at work wrote: Does that mean that Visual Studio user secrets will not work? Sorry, I do not know the defoinitive answer, but there is a section on that page titled "Migrating User Secrets from ASP.NET Framework to ASP.NET Core", which may help.
|
|
|
|
|
I've finished reading the document and I did see that "*Migrating User Secrets from ASP.NET Framework to ASP.NET Core*". Unfortunately, that won't work for me. I wish we were allowed to update code, but the motto where I work is, "If the code isn't broken beyond repair, do NOT modify it!! And NEVER, EVER update or upgrade it!!!" I have no choice but to work on old code using whatever .NET Framework it was originally written in. And some of those dates back to .NET Framework 1.1.
Rod
|
|
|
|
|
Another issue I'm unclear on, in reference to that "Safe storage" document, is the use of environmental variables for safely storing secrets. The document brings up environmental variables, saying that is a safe way to use secrets securely, then drops talking about environmental variables. Please excuse my abysmal ignorance on how to use environmental variables on a development machine, on the deployed server and an Azure App Service. How does that work?
Rod
|
|
|
|
|
Sorry, I have not studied the paper in detail. I think you may need to ask Microsoft for clarification.
|
|
|
|
|
Rod at work wrote: The only thing is, how do I do that
By providing a key that only shows up on a developer machine. Such as a specific single env variable. It only exists on dev machines. The code uses different code based on whether that exists or not.
The env variable does not provide security information itself. It just exists.
That allows for no security problems because if it starts existing on a prod box nothing will work.
This solves your github problem.
Rod at work wrote: However, we have hundreds of custom apps...And NEVER, EVER update or upgrade it!!!
(From other posts)
Which is exactly correct. If you bring an app forward then that tech debt activity should make NO functional changes except those necessary to bring it forward. These days one can often make that case to do that for existing code both for obsolesce and security reasons.
But besides that presumably those apps are already managing secret information via some mechanism and you should not attempt to use another idiom unless there is a real need. It does not add value to have multiple idioms that one must know to provide maintenance and just to do development.
|
|
|
|
|
I'm going to consider what you've said here concerning environmental variables. You've given me some things to think about.
I did want to respond to your suggestion of not changing the idiom for how we handle secrets to another idiom. In this case I believe we will have to when migrating to repos in GitHub. As I understand GH Advanced Security, it will run a check on attempted commits to see if secrets are in the proposed commit. If secrets are there, then the commit/push will be rejected. Secrets are in all our source code. (If I've misunderstood how GH Advanced Security works, with respect to secrets, then please forgive and correct me.)
Rod
|
|
|
|
|
Rod at work wrote: Secrets are in all our source code.
Well that is a problem!
Perhaps you should find a solution for the older apps first. Updating only that part.
Only then, and to be a consistent, new apps would use it in the same way.
Not to give away a secret though - I doubt github can find all secrets. So you can probably find a way to obfuscate in the code. But that should be a stopgap.
|
|
|
|
|
Hi!
I'm a beginner in C# and need some help.
In Winforms I've got a button. When I press the button I'd like to get some data from TMDB and insert it to MS SQL.
I've redacted some properties to cut down unnecessary properties.
This is what I've got:
Forms.cs:
public void btn_GetNewTVShowData_Click(object sender, EventArgs e)
{
GetTMDB GetData = new GetTMDB();
GetData.GetTvShowData();
}
DataClasses\Common\GetTMDB.cs
DataClasses\Common\GetTMDB.cs
namespace WinFormsApp1.DataClasses.Common
{
internal class GetTMDB
{
public async Task<string> GetTvShowData()
{
HttpClient client = new HttpClient();
var content = await client.GetStringAsync("https://api.themoviedb.org/3/tv/136311?api_key=XXXXXXX&language=en-US");
TVShow myDeserializedClass = JsonConvert.DeserializeObject<TVShow>(content);
return object myDeserializedClass; <-- Not working, I know
}
public class TVShow
{
public string backdrop_path { get; set; } = default!;
public List<CreatedBy> created_by { get; set; } = default!;
public string name { get; set; } = default!;
}
public class CreatedBy
{
public int id { get; set; } = default!;
public string credit_id { get; set; } = default!;
public string name { get; set; } = default!;
public int gender { get; set; } = default!;
public string profile_path { get; set; } = default!;
}
}
}
DataClasses\Common\DataAccess.cs (psedocode, just for showing I want it in seperate class)
INSERT INTO table_name (column1, column2) VALUES (value1, value2);
So, I want to press a button, use the class GetTMDB, get the json from TMDB, Serialize it (with NewtonSoft.json), return the data back to my forms1.cs (I guess? Or should I call DataAccess.cs?).
Is it possible to let another class access the properties?
Let's say I want multiple classes to access the Properties to do different kind of stuff with my properties.
|
|
|
|
|
You have way too many things going on (for a "beginner"), and that are wrong. You need to pick some aspect and ask for help on that instead of asking for what amounts to a course in C# programming and systems design.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
First, you're return type is a Task<string>, not what you're really returning, so you have to fix that.
Next, the return statement just needs the "object" part removed.
Lastly, the other answer is correct. You're jumping in the deep end without knowing how to swim.
This is NOT tested, so don't go expecting this to work immediately:
public async TVShow GetTvShowData()
{
HttpClient client = new HttpClient();
var content = await client.GetStringAsync("https://api.themoviedb.org/3/tv/136311?api_key=XXXXXXX&language=en-US");
TVShow myDeserializedClass = JsonConvert.DeserializeObject<TVShow>(content);
return myDeserializedClass;
}
|
|
|
|
|
I'm a bit confused on something.
I have a Sharepoint class with a DownloadFileAsync method:
using System.IO;
using System.Threading.Tasks;
namespace WpfApp1
{
internal class Sharepoint
{
public async Task DownloadFileAsync(string folderName, string downloadPath = null)
{
var url = _clientContext.Web.ServerRelativeUrl + "/Shared%20Documents/" + folderName;
Folder targetFolder = _clientContext.Web.GetFolderByServerRelativeUrl(url);
_clientContext.Load(targetFolder.Files);
await _clientContext.ExecuteQueryAsync();
foreach (var file in targetFolder.Files)
{
FileInformation sharepointFile = Microsoft.SharePoint.Client.File.OpenBinaryDirect(_clientContext, file.ServerRelativeUrl);
await _clientContext.ExecuteQueryAsync();
var path = string.IsNullOrEmpty(downloadPath) ? DEFAULT_DIRECTORY : downloadPath;
path = path + @"\" + file.Name;
using (FileStream filestream = new FileStream(path, FileMode.Create))
{
sharepointFile.Stream.CopyTo(filestream);
}
}
}
}
}
It is called from a Repository class
using System.IO;
using System.Threading.Tasks;
namespace WpfApp1
{
internal class Repository
{
string _appPath;
Sharepoint _sharePoint;
public Repository()
{
_sharePoint = new Sharepoint();
_appPath = $"{Path.GetTempPath()}RDSPaymentProcessing";
}
public async Task<MyData> GETDataAsync()
{
var results = new MyData();
var fileName = $"{Path.GetTempPath()}{LOCAL_APP_DATA_FOLDER}\sharepointdata.xml";
if (File.Exists(fileName))
{
File.Delete(fileName);
}
await _sharePoint.DownloadFile(SETINGS_FOLDER, _appPath);
if (File.Exists(fileName))
{
results = Serialization.DeSerializeObject<MyData>(fileName);
}
else
{
throw new FileNotFoundException(fileName);
}
return results;
}
}
}
and that is called from the MainWindowViewModel's loaded method:
namespace WpfApp1
{
internal class MainWindowViewModel
{
private MyEntity _data;
public async void WindowLoadedExecuted()
{
await _repository.GETDataAsync();
}
}
}
The question is about where to use await/async? I want to UI to be responsive throughout all of this? Am I coding this right? Or does await/async only need to be on the Sharepoint class?
In theory, theory and practice are the same. But in practice, they never are.”
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
|
|
|
|
|