|
|
Your design in not in "third normal form". This app will always be a pain.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
any idea in mind or best alternative with same output? instead of using dictionary to store and compare data?
|
|
|
|
|
If you "normalize": {key,item,qty} you could "aggregate" files by subtracting one from the other (with same key,item); any items with a "balance" are obviously different.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
You need to specify the result you want in more detail.
0. if each dictionary has an identical key, but the key's values are different, what do you want to do ?
a. keep the value from one of the two dictionaries ? which one ?
b. execute some comparison function you define ?
1. do you assume Key and Value are the same Types ?
2. assuming #1: what if one dictionary has a KVPair with a key 'foo, and the other dictionary has a KVPair with a value of 'foo ?
See if this gives you some ideas:
private Dictionary<int, int> d1 = new Dictionary<int, int> {{1, 10}, {2, 20}, {3, 40}};
private Dictionary<int, int> d2 = new Dictionary<int, int> {{1, 12}, {2, 20}, {5, 40}, {6, 50}};
private Dictionary<T1,T2> GetDictDiff<T1, T2>(Dictionary<T1, T2> d1, Dictionary<T1, T2> d2)
{
Dictionary<T1,T2> kvpDifferences = new Dictionary<T1, T2>();
foreach (KeyValuePair<T1, T2> kvp in d1)
{
if (! d2.Keys.Contains(kvp.Key))
{
kvpDifferences.Add(kvp.Key, d1[kvp.Key]);
}
else
{
if (! Equals(d2[kvp.Key], d1[kvp.Key]))
{
kvpDifferences.Add(kvp.Key, d1[kvp.Key]);
}
}
}
foreach (KeyValuePair<T1, T2> kvp in d2)
{
if (! d1.Keys.Contains(kvp.Key))
{
kvpDifferences.Add(kvp.Key, d2[kvp.Key]);
}
}
return kvpDifferences;
}
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
modified 20-Jan-20 3:28am.
|
|
|
|
|
It's difficult to answer your question without knowing precisely which types you're using.
Assuming you're using a dictionary of dictionaries:
var dictionary1 = new Dictionary<int, Dictionary<int, int>>
{
[1] = new Dictionary<int, int>
{
[1] = 10,
[2] = 20,
[3] = 40,
},
[2] = new Dictionary<int, int>
{
[1] = 15,
[2] = 28,
[3] = 40,
},
[3] = new Dictionary<int, int>
{
[1] = 15,
[2] = 28,
[3] = 40,
},
};
var dictionary2 = new Dictionary<int, Dictionary<int, int>>
{
[1] = new Dictionary<int, int>
{
[1] = 12,
[2] = 20,
[3] = 40,
},
[2] = new Dictionary<int, int>
{
[1] = 15,
[2] = 25,
[3] = 40,
},
[3] = new Dictionary<int, int>
{
[1] = 15,
[2] = 28,
[3] = 40,
},
}; and you want to keep the values from dictionary2 , then something like this should work:
var result = new Dictionary<int, Dictionary<int, int>>();
foreach (var pair in dictionary2)
{
if (!dictionary1.TryGetValue(pair.Key, out var value))
{
result.Add(pair.Key, pair.Value);
}
else
{
var differences = new Dictionary<int, int>();
foreach (var item in pair.Value)
{
if (!value.TryGetValue(item.Key, out var i) || item.Value != i)
{
differences.Add(item.Key, item.Value);
}
}
if (differences.Count != 0)
{
result.Add(pair.Key, differences);
}
}
} NB: Items in the first dictionary (or one of its nested dictionaries) which are not in the second dictionary will be ignored.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
hi Richard,
var dictionary1 = new Dictionary<int, string="">
var dictionary2 = new Dictionary<int, string="">
KeyValue Item
1 {item 1, 10; item 2, 20; item 3, 40}
2 {item 1, 15; item 2, 28; item 3, 40}
3 {item 1, 15; item 2, 28; item 3, 40}
there are 3 pairs each keys has multiple string. main problem is to compare the diff in string. Keys are assumed to be the same.
|
|
|
|
|
If you're storing the value as a string in that format, then you're going to need to write custom code to parse that format to extract the keys and values from it.
For example:
private static readonly Regex ItemPattern = new Regex(@"^\s*{\s*(?<key>[^,]+)\s*,\s*(?<value>[^;]+)(\s*;\s*(?<key>[^,]+)\s*,\s*(?<value>[^;]+))*\s*}\s*$", RegexOptions.ExplicitCapture);
private static Dictionary<string, string> ParseItem(string value)
{
var match = ItemPattern.Match(value);
if (!match.Success) throw new ArgumentException($"Item '{value}' is not in the correct format.", nameof(value));
var keys = match.Groups["key"].Captures.Cast<Capture>();
var values = match.Groups["value"].Captures.Cast<Capture>();
return keys.Zip(values, (k, v) => (key: k.Value, value: v.Value)).ToDictionary(p => p.key, p => p.value);
}
private static string FormatItem(Dictionary<string, string> value)
{
if (value.Count == 0) return null;
return "{" + string.Join("; ", value.Select(p => $"{p.Key}, {p.Value}")) + "}";
}
private static string FindChanges(string source, string target)
{
var sourceItem = ParseItem(source);
var targetItem = ParseItem(target);
var result = new Dictionary<string, string>();
foreach (var pair in targetItem)
{
if (!sourceItem.TryGetValue(pair.Key, out var value) || pair.Value != value)
{
result.Add(pair.Key, pair.Value);
}
}
return FormatItem(result);
} With that in place, you can adapt my previous answer to find the differences:
var dictionary1 = new Dictionary<int, string>
{
[1] = "{item 1, 10; item 2, 20; item 3, 40}",
[2] = "{item 1, 15; item 2, 28; item 3, 40}",
[3] = "{item 1, 15; item 2, 28; item 3, 40}",
};
var dictionary2 = new Dictionary<int, string>
{
[1] = "{item 1, 12; item 2, 20; item 3, 40}",
[2] = "{item 1, 15; item 2, 25; item 3, 40}",
[3] = "{item 1, 15; item 2, 28; item 3, 40}",
};
var result = new Dictionary<int, string>();
foreach (var pair in dictionary2)
{
if (!dictionary1.TryGetValue(pair.Key, out var value))
{
result.Add(pair.Key, pair.Value);
}
else if (value != pair.Value)
{
result.Add(pair.Key, FindChanges(value, pair.Value));
}
} Output:
[1] = "{item 1, 12}"
[2] = "{item 2, 25}"
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I have two apps. One converts an Access database into SQL. It uses the Microsoft.ACE.OLEDB.12.0' provider. This works fine.
My second app reads Excel files into SQL. It uses the same Microsoft.ACE.OLEDB.12.0' provider. However, when I run it, I get
'The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine
Access Conversion App
private void ConnectToAccess(string accessDB)
{
try
{
connString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={accessDB};Persist Security Info = False;";
acccessConn = new OleDbConnection(connString);
acccessConn.Open();
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
}
Excel Conversion App
private static DataSet ToDataSet(string excelFile, int startRecord = 0, int maxRecord = -1, string condition = "")
{
DataSet result = new DataSet();
string connString = connString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={excelFile};Extended Properties=Excel 12.0;HDR=No;IMEX=1";
using (OleDbConnection connection = new OleDbConnection(connString))
{
try
{
connection.Open();
DataTable schema = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
foreach (DataRow drSheet in schema.Rows)
{
if (drSheet["TABLE_NAME"].ToString().Contains("$"))
{
string s = drSheet["TABLE_NAME"].ToString();
if (s.StartsWith("'"))
{
s = s.Substring(1, s.Length - 2);
}
var command = new OleDbDataAdapter(string.Join("", "SELECT * FROM [", s, "] ", condition), connection);
DataTable dt = new DataTable();
if (maxRecord > -1 && startRecord > -1)
{
command.Fill(startRecord, maxRecord, dt);
}
else
{
command.Fill(dt);
}
result.Tables.Add(dt);
}
}
return result;
}
catch (Exception ex)
{
throw;
}
finally
{
connection.Close();
}
}
}
How can this work for one and not the other??
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Simple: the ACE DB engine comes in to versions: 32 bit and 64 bit. If you have the 64 bit engine installed, a 64 bit app can use it, but a 32 bit version can't - and vice versa.
You can install both versions on the same machine: Installing 32-bit and 64-bit Microsoft Access Drivers next to each other[^]
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
OriginalGriff wrote: You can install both versions on the same machine
I tried already. The installer for the 64-bit throws
You cannot install the 64-bit version of Microsoft Access Database Engine 2010 because you currently have 32-bit Office producs installed.
The 32 bit installer prompts me to repair.
UPDATE
When I try the 64 bit installation from the command line with Passive, then run my app, I get "Could not find installable ISAM."
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
modified 15-Jan-20 15:42pm.
|
|
|
|
|
Did you try following the link?
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
|
Or you could just force your app to compile 32-bit only. See Project -> Properties -> Build tab.
|
|
|
|
|
This is getting better by the minute.. I recompiled as x86 and it threw '亘è応眅徸眅'
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
I have no clue what that's about.
|
|
|
|
|
關於我的世界
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
In this example from my DAL, both THROWs would be caught by my Global Exception handler, which logs the error, pops up a "Error Occured" dialog, and shuts down the app.
public void DeleteRole(int id)
{
try
{
var role = (from u in dataContext.Roles
where u.Id == id
select u).FirstOrDefault();
var hasUsers = (from u in dataContext.Users
where u.RoleId == id
select u).Any();
if (hasUsers)
{
throw new Exception($"The role '{role.RoleName}' cannot be deleted because it has users assigned to it." );
}
else
{
if (role != null)
{
role.IsDeleted = true;
dataContext.SubmitChanges();
}
}
}
catch (Exception)
{
throw;
}
}
So, how would you allow the user exception to be handled without closing the app? I'd like the message of the exception to appear in a MessageBox.
I could replace those types of exceptions with a custom exception, the catch those before the global handler gets it.
What's the right way to handle this?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Don't throw a "global exception", throw an Application Exception
throw new ApplicationException($"The role '{role.RoleName}' cannot be deleted because it has users assigned to it." );
You can then catch just those and report them:
catch (ApplicationException aex)
{
MessageBox.Show(aex.Message);
return;
}
catch (Exception ex)
{
... Or better, don't throw an exception if your code is going to handle it in the same method - report the problem directly in your code instead, and return from the method.
Exceptions shouldn't be used as a form of flow control!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
You shouldn't use exceptions for things that are expected. If dealing with deleting roles that might have users attached is part of your business logic flow then it isn't an exception, it is a predicted possible outcome. If there is only one way the remove could fail (barring actual exceptions like your database not being available etc) then make your method return a bool and return false if the role has users and your calling code can report that to the UI. Or you could return an enum that has values like
Success
RoleHasUsers
SomeOtherPossibleFailure
and return the appropriate enum and again have the calling code report to the UI.
|
|
|
|
|
Kevin Marois wrote:
catch (Exception)
{
throw;
} If your catch block is simply re-throwing the same exception, without adding any extra information to it, then you don't need the catch block at all.
And as Griff said, don't use throw new Exception(...); - use a specific exception type instead. Either one of the built-in exception types, or a custom exception type will do. That way, the calling code has a better chance of catching just the exceptions it can handle, without having to look at the Message to try to work out what the problem is.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I give the user the option to retry at the application level instead of abandoning them with a "shut down".
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Ive already searched for infomation how I can do that but I cant fix this problem. I want to add a weather-widget to my webpage. It works using latitude and longitude. I want it should desplay the current weather from where the user is now.
<span id ="long"></span>
<script type='text/javascript' id="weather-link" src='https://darksky.net/widget/default/></script>
<script>const weatherLink = $("#weather-link");
weatherLink.html("<span id=\"" + response.latitude + "," +response.longitude + "\">/uk12/de.js?width=100%&height=350&title=Basel&textColor=333333&bgColor=FFFFFF&transparency=false&skyColor=undefined&fontFamily=Default&customFont=&units=uk&htColor=333333<Color=333333&displaySum=yes&displayHeader=yes</span>");
weatherLink.attr("src", weatherLink.attr("src") + response.city);</script>
The following code I use it to get users information. It works well
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$("#long").html(response.latitude + ", " + response.longitude );
$("#response").html(JSON.stringify(response, null, 4));
}, "jsonp");
</script>
I need to add to src a text that changes using that code above. THX
|
|
|
|
|
|