I'm doing a CollectionAssert for two public lists built from linq-to-sql queries. When I do the CollectionAssert for these, it always fails even for a test set which clearly should pass.
I even did a quick test in my code to make sure I'm using the CollectionAssert correctly.
//This always passes
List<string> testList1 = new List<string>();
List<string> testList2 = new List<string>();
testList1.Add("one");
testList2.Add("two");
testList2.Add("three");
testList2.Add("one");
CollectionAssert.IsSubsetOf(testList1, testList2);
//This always fails
CollectionAssert.IsSubsetOf(memberOrganizations, member_Dim_Organization, "Error Matching Fields");
Any thoughts on how I can correct the syntax of the second assert? I've attached a screen shot of my debug window. Debug Screen Shot
I define the format of structure of the list in one method
namespace DefineStructure
{
public class Results
{
public string OrgID { get; set; }
}
This load the data in a separate
namespace Reporting.Member_Dim_Organization.ETL.QA
{
public class LoadData
{
public static cDataContext oMain = new cDataContext();
public static List<Results> oecMainResults = (from mo in oecMain.MemberOrganizations
orderby mo.OrgID
select new Results
{
OrgID = (mo.OrgID).ToString() }).Take(1).ToList();
Then I declare it in my main program
namespace Reporting.Main
{
[Binding]
public class Member_Dim_OrganizationsSteps
{
public static List<Results> memberOrganizations = LoadData.oecMainResults;
public static List<Results> member_Dim_Organization = LoadData.reportingMasterResults;
Does that help clarify?
Thanks for helping an old dog who's trying to learn some new tricks.
You are assuming that if the two collections have instances with the same data that they are equal, which is not the case by default. It sounds like you need to override Equals and GetHashCode on the Results class to define "equality".
There are lots of examples out there of defining equality for custom types, most of which involve defining the hash code as a combination of the hash codes of the fields that define equality.
Related
I have this class:
public class UserSet
{
public int One { get; set; }
public string Two { get; set; }
public string Three { get; set; }
}
And a static class:
public static class AllUsers
{
public static List<UserSet> Usersc = new List<UserSet>();
}
I always create new UserSet and then store it in Usersc. Basically I do this:
Data.UserSet setupSet = new Data.UserSet()
{
One = name,
Two = OsCislo,
Three = User.Identity.Name
};
Then I store it.
Data.AllUsers.Usersc.Add(setupSet)
Now what I want to do is:
Define setupSet
Check if setupSet is in Usersc.
If one (from my setupSet) is in Usersc then
3a) if setupSet is in Userc and everything is equal then don't do anything.
3b) If something is different then delete old UserSet in AllUsers and insert the new one
In code it will look like this:
Data.UserSet setupSet = new Data.UserSet()
{
One = name,
Two = OsCislo,
Three = User.Identity.Name
};
if (Data.AllUsers.Usersc.Select(s => s.One).ToList().Contains(User.Identity.Name))
{
// Always returns false for some reason
if (!Data.AllUser.Usersc.Contains(setupSet))
{
Data.AllUsers.Usersc.Remove(Data.AllUsers.Usersc.Where(s => s.One == User.Identity.Name).ToList().First());
Data.AllUsers.Usersc.Add(setupSet);
}
}
else
{
Data.AllUsers.Usersc.Add(setupSet);
}
As you can see, problem is in my if statement where I try to get whether setupSet is inside Usersc but for some odd reason it always returns false even though setupSet should be inside it.
This is because your line of code Data.AllUser.Usersc.Contains(setupSec) compares references - not values of the properties of objects in the list.
You create your setupSet object at the top without adding it to the list - so this list doesn't contain it. Despite the fact that two objects have exactly the same values of properties for .net these are two different objects. Therefore list.Contains() return false.
So to solve your problem there are 2 ways:
Don't use Contains() method of List - and use LINQ expression comparing properties that are crucial for your understanding equality of 2 objects of your UserSet class
Definitely better - implement Equals method inside your UserSet class that will tell the CLI what do you understand as EQUAL if it comes to your class.
Take a look at the following code (please bear in mind that this is a naive implementation):
void Main()
{
var myList = new List<SomeClass>();
var o1 = new SomeClass{SomeProperty = "foo"};
myList.Add(o1);
var o2 = new SomeClass{SomeProperty = "foo"};
if(myList.Contains(o2))
{
"List Contains element".Dump();
}
else{
"List does not contain element".Dump();
}
}
private class SomeClass{
public string SomeProperty {get;set;}
public override bool Equals(object obj)
{
var casted = obj as SomeClass;
if(casted == null) return false;
if(string.Equals(casted.SomeProperty, this.SomeProperty)) return true;
return false;
}
}
Here I told the .NET what it means for me that 2 instances of my SomeClass are equal by overriding the {public bool Equals(object obj)} method.
Inside of that method I write that 2 objects are equal if value of SomeProperty is the same.
if(string.Equals(casted.SomeProperty, this.SomeProperty)) return true;
Therefore in the console, I can see "List Contains element". If you remove that override Equal the console will say "List does not contain the element".
Last but not least as Blindy wrote - use thread-safe collection. It will make your example better (however I don't believe that threads are the problem that you described).
You can also dive deeper into in-memory database in Entity Framework - you will not have to create that static class with a static collection of elements (which is a mock of database of cache I believe). It is super-easy
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "My_DB")
.Options;
var context = new ApplicationDbContext(options);
even tho setupSet should be inside it
There's a reason static is rarely used in Asp.Net projects, of any kind: there are multiple threads that handle your requests, and if they're all fighting over the same List<>, that's a recipe for disaster.
Either use a synchronized collection (like ConcurrentSet<> or ConcurrentBag<>), or use a crude locking mechanism, or something to make sure you don't trample one thread's list access from another.
Or even better, use a database to store data. That's what it's made for, and most DBMS are transactional, so they handle multi-threaded access safely for you.
I'm pretty new to programming, and I'm teaching myself. Any and all help is appreciated, but please be understanding -- I don't really know what I'm doing that well. Also, this is the first question I've ever posted on SO (I sure have read a lot of other people's, so thanks for all that), so if I need to modify anything about how I'm asking, please let me know. Thanks!
I'm working on creating a Xamarin application in Visual Studio.I created a mock database to serve mock information to my application. The MockDatabase file is a POCO with static lists to hold the information. There are 11 lists for the models that I created that will eventually map to the SQLite database file I'm planning to use in the future. Here's a snapshot of the file:
public class MockDatabase : IDataStore
{
public static List<tblAddress> Addresses { get; set; }
public static List<tblCrew> Crews { get; set; }
public static List<tblCustomer> Customers { get; set; }
public static List<tblEmployee> Employees { get; set; }
//etc...
public MockDatabase(bool createMockData = false)
{
if (createMockData)
{
Addresses = Addresses ?? MockData.MockAddresses();
Crews = Crews ?? MockData.MockCrews();
Customers = Customers ?? MockData.MockCustomers();
Employees = Employees ?? MockData.MockEmployee();
//etc...
}
}
The static modifier does what I want, that even if I initialize multiple instances of the class, each of them points to the same static instance of the list. So, the problem that I'm having with using static lists is that it works too well. When I run my unit tests in a consecutive run, the tests are getting the data that a previous test set, which meant I had to rewrite the tests to account for this. I solved the problem by calling MockDatabase.Addresses = new List<tblAddress>(); in my test initialization, but I really wanted to use something that would work more broadly, and not need to be specialized for each test class that I'm creating.
Here's what I had written:
[TestClass]
public class AddressRepositoryTests
{
[TestInitialize]
public virtual void SetUp()
{
MockDatabase.Addresses = new List<tblAddress>();
}
But what I was trying to accomplish was to have the MockDatabase use some reflection to find all lists within itself and reset their value. I tried a number of variations on the following code, but I couldn't find anything that worked.
[TestClass]
public class AddressRepositoryTests
{
[TestInitialize]
public virtual void SetUp()
{
(new MockDatabase()).ClearDatabase();
}
public void ClearDatabase()
{
var properties = typeof(MockDatabase).GetProperties();
foreach (var property in properties)
{
if (property.PropertyType == typeof(IList<BaseModel>))
{
property.SetValue(this, null);
}
}
}
I put a break point inside the if statement and tried a number of different code variations, and nothing ever returned true.
Thanks for any help!
Edit
I don't know how to use the generic List<T> in the middle of a method. Sticking it into the line produces the compiler error "The type or namespace T could not be found..."
if (property.PropertyType == typeof(IList<T>)) //Will not compile
I also tried comparing against List<object>, but that fails too.
if (property.PropertyType == typeof(IList<object>)) //Fails
Could you try changing ClearDatabase function as below:
public void ClearDatabase()
{
var properties = typeof(MockDatabase).GetProperties();
foreach (var property in properties)
{
if (property.PropertyType.Name == typeof(List<>).Name || property.PropertyType.Name == typeof(IList<>).Name)
{
property.SetValue(this, null);
}
}
}
I have found some threads with similar titles, but none seem to have a fitting answer.
One mentioned a bug in .NET versions prior to 4.0 - I use 4.0, so this should not be it.
Consider the example:
I am attempting to create a collection of instances of class Part, which do not belong to any instance of class PartGroup.
Func<Part,bool> hasGroup = P => partColl.Groups.Any( G => G.Parts.Contains(P) );
var groupless = partColl.Parts.Where( P => ! hasGroup(P) );
partColl is an instance of a class implementing the properties Groups and Parts, each IEnumerable<T> where T is PartGroup or Part respectively, internally implemented as List<T>.
partColl.Parts contains all parts in existence.
class Group has property IEnumerable<Part> Parts, listing references to parts belonging to the group.
In my current program, there are 27 parts and 5 groups with no overlap in elements.
Nothing that should trouble the stack, despite quadratic complexity, if something wasn't foul.
When I run this, it will crash with said exception on hasGroup.
What am I missing?
EDIT:
A little detail slipped my abstraction presented here:
IEnumerable PartGroup.Parts was, unlike the two properties of PartCollection, not backed by a List, it was an auto-property with private set, initialized in the c'tor with a passed-in IEenumerable. The instance behind this IEnumerable is also a list, and an own one for each group, so I'm not sure yet what is going on exactly.
BUT, the exception is gone by: also backing that property with a variable of type List and in the constructor, assigning to it: _list = parts.ToList(), where parts is IEnumerable<Parts>, passed as a param to the ctor. I did ToList just to make sure it will really be a list, not some half baked query, but it should, since at the place where I am building the groups, one new List for each group is allocated before passing it in...
The remaining question is still interesting: What was going on, why did the auto-property 'cause' the exception?
I'll post more details on request, but gotta go for a while now.
This small sample does not reproduce the issue.
using System;
using System.Linq;
using System.Collections.Generic;
class P
{
class PartGroup
{
public List<Part> Parts { get; private set; }
public PartGroup()
{
Parts = new List<Part>();
}
}
class Part
{
}
class PartCollection
{
public List<Part> Parts { get; set; }
public List<PartGroup> Groups { get; set; }
public PartCollection()
{
Parts = new List<Part>();
Groups = new List<PartGroup>();
}
}
static void Main()
{
var groups = new List<PartGroup> { new PartGroup(), new PartGroup(), new PartGroup(), new PartGroup(), new PartGroup() };
var partColl = new PartCollection();
partColl.Parts.Add(new Part());
partColl.Groups.AddRange(groups);
for (int i = 0; i < 27; i++)
{
var part = new Part();
groups[i % groups.Count].Parts.Add(part);
partColl.Parts.Add(part);
}
partColl.Parts.Add(new Part());
Func<Part, bool> hasGroup = P => partColl.Groups.Any(G => G.Parts.Contains(P));
var groupless = partColl.Parts.Where(P => !hasGroup(P)).ToList();
}
}
I am looking to find a way to take two objects that have identical properties and make a call to copy the property values from one object into the other. The the example below assume I have an instance of A and I want to use the data of that instance to hydrate a new instance or C (to keep things terse I used fields instead of properties in the example below)
public class A : B
{
public string prop1;
public int prop2;
}
public class B
{
public byte propX;
public float propY;
}
public class C
{
public byte propX;
public float propY;
public string prop1;
public int prop2;
}
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
//do some work
//maybe <T> generically refactor?
}
}
The merger class is just a psuedo-example, doing this through generics would be optimal but the first thing I question is whether such a capability already exists. I could imagine using reflection to do this myself but just wanted to toss it out for better ideas first.
Real world context: This is actually an MVVM related issue as I am trying to use disparate classes coming back from EF to populate a ViewModel instance.
Check out tools and libraries like AutoMapper - those would handle cases like this with ease - and much more! No need to re-invent the wheel - just use the tool! :-)
You would basically define a map between classes A and C like this:
Mapper.CreateMap<A, C>();
and then later on, you can have AutoMapper do the mapping, based on that map, from an instance of A into an instance of C, something like this:
C yourC = Mapper.Map<A, C>(instanceOfA);
AutoMapper does a default mapping based on property names (and types), but you can extend and influence it in a great many ways to include mappings from one property to another, even if the names (or types) don't match 100%. It's quite flexible and well established - definitely worth a serious look!
using System;
using System.Linq;
using System.Reflection;
public class Merger
{
public static TTarget Merge<TTarget>(object copyFrom) where TTarget : new()
{
var flags = BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic;
var targetDic = typeof(TTarget).GetFields(flags)
.ToDictionary(f => f.Name);
var ret = new TTarget();
foreach (var f in copyFrom.GetType().GetFields(flags))
{
if (targetDic.ContainsKey(f.Name))
targetDic[f.Name].SetValue(ret, f.GetValue(copyFrom));
else
throw new InvalidOperationException(string.Format(
"The field “{0}” has no corresponding field in the type “{1}”.",
f.Name, typeof(TTarget).FullName));
}
return ret;
}
}
class Program
{
static void Main(string[] args)
{
var a = new A { prop1 = "one", prop2 = 2, propX = 127, propY = 0.47f };
var c = Merger.Merge<C>(a);
Console.WriteLine(c.prop1); // prints one
Console.WriteLine(c.prop2); // prints 2
Console.WriteLine(c.propX); // prints 127
Console.WriteLine(c.propY); // prints 0.47
}
}
This isn't the best solution by far, but based on the object graph you've provided, you could probably accomplish this by XML serializing the first object, and XML deserializing the XML stream into the second object.
Your proposed Merger method could possibly look like this:
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
var xmlContent = MyXMLSerializationMethod(copyFrom);
MyXMLDeserializationMethod(xmlContent, typeof(copyTo), out copyTo);
return copyTo;
}
}
Good post about using AutoMapper to solve this problem in the context of MVVM and MVC
http://www.bengtbe.com/blog/post/2009/04/14/Using-AutoMapper-to-map-view-models-in-ASPNET-MVC.aspx
I have the following class:
public class Item
{
public Dictionary<string, string> Data
{
get;
set;
}
}
and a list of it:
List<Item> items;
I need to filter and order this list dynamically using SQL-Like strings. The catch is, that I need to order it by the Data dictionary.
For example: Order By Data["lastname"] or Where Data["Name"].StartsWith("a"). I thought to use the dynamic linq library, but is there any way that my clients can write without the Data[]? For example:
Name.StartsWith("abc")
instead of
Data["Name"].StartsWith("abc")
?
You could add a property like this:
public class Item
{
public Dictionary<string, string> Data
{ get; set; }
public string Name { get { return Data["lastname"]; } }
}
//Call by: i.Name.StartsWith("abc");
Or an extension method:
public static class ItemExtensions
{
public static string Name(this Item item)
{
return item.Data["lastname"];
}
}
//Call by: i.Name().StartsWith("abc");
Or if it's a very commonly used method, you could add something like a .NameStartsWith():
public static string NameStartsWith(this Item item, stirng start)
{
return item.Data["lastname"].StartsWith(start);
}
//Call by: i.NameStartsWith("abc");
This doesn't have anything to do with the Linq Dynamic Query unit. That unit is for when you have actual fields/properties and the names of them will be given to you at runtime. In other words, you have a class like this:
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
And you want to be able to write a query like this:
var sortedPeople = people.OrderBy("FirstName");
You are trying to do the exact opposite of this - you have a class that does not have any actual properties, just an attribute dictionary, and you want compile-time safety. You can't have it; there's no way to guarantee that an item will be in the dictionary, especially when the dictionary is public and anyone can add/remove directly from it!
If there's some reason that you must use that specific class design, then you could conceivably write some wrappers as Nick has presented, but I wouldn't even bother - they're not actually providing any encapsulation because the Data dictionary is still wide open to the whole world. Instead, I would just provide a single safe getter method or indexer property and create a few constants (or an enum) with the names of properties you expect to be in there.
public class Item
{
public Dictionary<string, string> Data { get; set; }
public string GetValue(string key)
{
if (Data == null)
return null;
string result;
Data.TryGetValue(key, out result);
return result;
}
}
public class ItemKeys
{
public const string Name = "Name";
public const string Foo = "Foo";
}
And so on. Really the ItemKeys isn't that important, the safe GetValue method is what's important, because otherwise you run the risk of a NullReferenceException if Data hasn't been assigned, or a KeyNotFoundException if even one Item instance doesn't have that property. Using the GetValue method here will succeed no matter what:
var myItems = items.OrderBy(i => i.GetValue(ItemKeys.Name));
If you find you're writing a lot of repetitive code for the same attributes, then start worrying about adding shortcut properties or extension methods to the class.
I assume that you don't know the names of the properties at compile-time (in which case, you could simply define properties and wouldn't have this problem). I have two suggestions that you could try, but I didn't implement any of them myself, so I can't guarantee that it will work.
If you can use .NET 4.0, you could inherit from DynamicObject and implement TryGetMember method (which is called when you use o.Foo on an object that is declared as dynamic). Assuming that Dynamic LINQ works with DLR, it should automatically invoke this method for objects that inherit from DynamicObject. Inside the TryGetMember method, you would get a name of the accessed property, so you could perform a dictionary lookup. (However, this solution would work only if Dynamic LINQ integrates well with DLR).
In any case, you could do some basic parsing of the string entered by the user and replace for example Name with Data["Name"]. This would definitely work, but it may be a bit difficult (because you should probably at least check that you're doing the replace in correct context - e.g. not inside a string constant).
Regarding extension methods - I'm not sure if Dynamic LINQ handles extension methods (but, I don't think so, because that would require searching all referenced assemblies)