Why doesn't Autofixture Likeness behave like I'd expect for one of these two tests? - autofixture

Given these classes:
public class DrumAndBassBand
{
public Drums Drum { get; set; }
public Bass Bass { get; set; }
}
public class Instrument
{
public string Name { get; set; }
public int SerialNumber { get; set; }
}
public class Drums : Instrument { }
public class Bass : Instrument { }
Why does this test pass...
[Fact]
public void DrumAndBassBand_Equality_Behaves_As_Expected_Version_One()
{
// arrange
var template = new Fixture().Create<DrumAndBassBand>();
// act
var createdBand = new DrumAndBassBand {Drum = template.Drum, Bass = template.Bass};
// assert
var createdLikeness = createdBand.AsSource().OfLikeness<DrumAndBassBand>()
.Without(x => x.Bass)
.CreateProxy();
createdLikeness.Drum = createdBand.Drum;
Assert.True(createdLikeness.Equals(template));
var templateLikeness = template.AsSource().OfLikeness<DrumAndBassBand>()
.Without(x => x.Bass)
.CreateProxy();
templateLikeness.Drum = template.Drum;
Assert.True(templateLikeness.Equals(createdBand));
}
...and this one fail? (the difference is the DrumAndBaseBand instantiation)
[Fact]
public void DrumAndBassBand_Equality_Behaves_As_Expected_Version_Two()
{
// arrange
var template = new Fixture().Create<DrumAndBassBand>();
// act
var createdBand =
new DrumAndBassBand
{
Drum = new Drums { Name = template.Drum.Name, SerialNumber = template.Drum.SerialNumber },
Bass = new Bass { Name = template.Bass.Name, SerialNumber = template.Bass.SerialNumber }
};
// assert
var createdLikeness = createdBand.AsSource().OfLikeness<DrumAndBassBand>()
.Without(x => x.Bass)
.CreateProxy();
createdLikeness.Drum = createdBand.Drum;
Assert.True(createdLikeness.Equals(template));
var templateLikeness = template.AsSource().OfLikeness<DrumAndBassBand>()
.Without(x => x.Bass)
.CreateProxy();
templateLikeness.Drum = template.Drum;
Assert.True(templateLikeness.Equals(createdBand));
}

In the second test, the Drum and Bass instances are different from the template where you are trying to compare.
You can always run a Likeness (without creating a Proxy) and inspect the output:
Test 'DrumAndBassBand_Equality_Behaves_As_Expected_Version_Two' failed:
Ploeh.SemanticComparison.LikenessException:
The provided value DrumAndBassBand did not match the expected value DrumAndBassBand.
The following members did not match:
- Drum.
That basically means that you have to provide a hint when creating a Likeness for the the comparison of the Drum instance.
The first half of the test becomes:
var createdLikeness = createdBand
.AsSource().OfLikeness<DrumAndBassBand>()
.With(x => x.Drum)
.EqualsWhen((s, d) => s.Drum == createdBand.Drum)
.Without(x => x.Bass)
.CreateProxy();
The source destination's Drums equals other Drums when it is really a createdBand instance Drum.
Similarly, the second half of the test becomes:
var templateLikeness = template
.AsSource().OfLikeness<DrumAndBassBand>()
.With(x => x.Drum)
.EqualsWhen((s, d) => s.Drum == template.Drum)
.Without(x => x.Bass)
.CreateProxy();
The above allow you to have very flexible comparisons (and you can always customize it even further).

Related

Error inserting data from many method return lists to a database in c#

I need help here with part of my code so here it is:
I have 6 methods as you can see below that parse incoming data and then returns it as a list, so my issue is to send that list data to my database table SerialNumber, each method of the lists is a separate field that will fill a database column.
So for example the parse material will fill the database materiallookupcode column and the same for the others.
Here is an image of the database table
Here is the code of all 5 methods that reads the data and then returns it and I need this data send to my database
private List<string> ParseMaterial()
{
var materialList = new List<string>();
foreach (var material in _connection.GetBarcodeList())
{
materialList.Add(material.Substring(10, 5));
}
return materialList;
}
private List<string> ParseLot()
{
var lotList = new List<string>();
var establishmentList = GetEstablishmentCode();
foreach (var lot in _connection.GetBarcodeList())
{
if (establishmentList.Contains("038"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.LoganSport038Property);
}
if (establishmentList.Contains("072"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.LouisaCounty072Property);
}
if (establishmentList.Contains("086"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.Madison086Property);
}
if (establishmentList.Contains("089"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.Perry089Property);
}
if (establishmentList.Contains("069"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.StormLake069Property);
}
if (establishmentList.Contains("088"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.Waterloo088Property);
}
if (establishmentList.Contains("265"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.GoodLetsVille265Property);
}
if (establishmentList.Contains("087"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.CouncilBluffs087Property);
}
if (establishmentList.Contains("064"))
{
lotList.Add(lot.Substring(28, 6) + _lotEstablishment.Sherman064Property);
}
}
return lotList;
}
private List<string> ParseSerialNumber()
{
var serialNumberList = new List<string>();
foreach (var serialNumber in _connection.GetBarcodeList())
{
serialNumberList.Add(serialNumber.Substring(36, 10));
}
return serialNumberList;
}
public List<string> ParseNetWeight()
{
var netWeightList = new List<string>();
foreach (var netWeight in _connection.GetBarcodeList())
{
netWeightList.Add(netWeight.Substring(22, 4));
}
return netWeightList;
}
public List<string> ParseGrossWeight()
{
var grossWeightList = new List<string>();
foreach (var grossWeight in _connection.GetBarcodeList())
{
grossWeightList.Add(grossWeight.Substring(22, 4));
}
return grossWeightList;
}
public List<string> FullBarcode()
{
var receiveFullBarcodeList = new List<string>();
foreach (var fullBarcode in _connection.GetBarcodeList())
{
receiveFullBarcodeList.Add(fullBarcode);
}
return receiveFullBarcodeList;
}
public List<string> GetEstablishmentCode()
{
var establishmentList = new List<string>();
foreach (var establishmentCode in _connection.GetBarcodeList())
{
establishmentList.Add(establishmentCode.Substring(36, 3));
}
return establishmentList;
}
The issue is here the button when clicking will read all 5 methods and send it to the database, I am sure the part where I making the list of variables to a string and the separator part is wrong so I need how is the correct way to add those list to each column of the database
private async void btn_SubmitData_Click(object sender, EventArgs e)
{
// parse list methodss
var materialList = ParseMaterial();
var lotList = ParseLot();
var netWeightList = ParseNetWeight();
var grossWeightList = ParseGrossWeight();
var serialNumberList = ParseSerialNumber();
var fullSerialNumberList = FullBarcode();
var material = "";
var lot = "";
var net = "";
var gross = "";
var serial = "";
var fullSerial = "";
var currentUser = _currentUser.GetCurrentUsernameOnApp();
var licensePlateId = GetLicensePlateIds();
for (var i = 0; i < _connection.GetBarcodeList().Count; i++)
{
material = materialList[i];
lot = lotList[i];
net = netWeightList[i];
gross = grossWeightList[i];
serial = serialNumberList[i];
fullSerial = fullSerialNumberList[i];
}
// database table and columns
var serialNumbersInsert = new List<SerialNumber>
{
new SerialNumber
{
SerialNumberLookupCode = serial,
NetWeight = Convert.ToDecimal(net) / 100,
GrossWeight = Convert.ToDecimal(gross) / 100,
LotLookupCode = lot,
MaterialLookupCode = material,
FullSerialNumberLookupCode = fullSerial,
CreatedSysDateTime = DateTime.Now,
ModifiedSysDateTime = DateTime.Now,
CreatedSysUser = currentUser,
ModifiedSysUser = currentUser,
LicensePlateId = licensePlateId
}
};
// insert to the database
foreach (var list in serialNumbersInsert)
{
_unitOfWork.SerialNumbers.Add(list);
}
await _unitOfWork.Complete();
}
Here is the SerialNumber domain class that represents a database table using a code first migration
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarcodeReceivingApp.Core.Domain
{
// domain class, represents a database table in sql server using code
// first migration
public class SerialNumber
{
public int Id { get; set; }
public int LicensePlateId { get; set; }
public string FullSerialNumberLookupCode { get; set; }
public string SerialNumberLookupCode { get; set; }
public decimal NetWeight { get; set; }
public decimal GrossWeight { get; set; }
public string LotLookupCode { get; set; }
public string MaterialLookupCode { get; set; }
public DateTime CreatedSysDateTime { get; set; }
public DateTime ModifiedSysDateTime { get; set; }
public string CreatedSysUser { get; set; }
public string ModifiedSysUser { get; set; }
}
}
I search other places but could not find a good solution so far, so any help is appreciate it.
I was able to resolve my question, what I did is to assign all lists in a loop and then assign them to each column in the database.
But I am still searching for a better and more clean way to this solution
private async void btn_SubmitData_Click(object sender, EventArgs e)
{
// parse list methods - represents each field of the database column
var materialList = ParseMaterial();
var lotList = ParseLot();
var netWeightList = ParseNetWeight();
var grossWeightList = ParseGrossWeight();
var serialNumberList = ParseSerialNumber();
var fullSerialNumberList = FullBarcode();
var currentUser = _currentUser.GetCurrentUsernameOnApp();
var licensePlateId = GetLicensePlateIds();
for (var i = 0; i < _connection.GetBarcodeList().Count; i++)
{
var serialNumbersInsert = new List<SerialNumber>
{
new SerialNumber
{
SerialNumberLookupCode = materialList[i],
NetWeight = Convert.ToDecimal(netWeightList[i]) / 100,
GrossWeight = Convert.ToDecimal(grossWeightList[i]) / 100,
LotLookupCode = lotList[i],
MaterialLookupCode = materialList[i],
FullSerialNumberLookupCode = fullSerialNumberList[i],
CreatedSysDateTime = DateTime.Now,
ModifiedSysDateTime = DateTime.Now,
CreatedSysUser = currentUser,
ModifiedSysUser = currentUser,
LicensePlateId = licensePlateId
}
};
foreach (var list in serialNumbersInsert)
{
_unitOfWork.SerialNumbers.Add(list);
}
await _unitOfWork.Complete();
}
}

Reference a scalar property from a string value

I have a combobox that contains a list of scalar properties of an entity. I need to do a search on the property specified by the user in the combobox.
How do I reference the property when I have it as a string?
Something similar to DBSet<> for entity.
Example:
if (order.Firstname != null && order.Firstname.ToLower().Contains(textBoxSearch.Text.ToLower()))
In the above example, I need to replace Firstname with Surname or any other property, at runtime, depending on what the user selected.
You can always use reflection, for your case you'll need something along these lines:
static void Main(string[] args)
{
var entity = new Entity {
Height = 172,
FirstName = "Foo",
Birthday = new DateTime(1, 1, 1995)
};
var firstName = GetEntityProperty<string>(entity, "FirstName");
}
public static T GetEntityProperty<T>(object entity, string propertyName)
{
var type = entity.GetType();
var property = type.GetProperty(propertyName);
return (T)property.GetValue(entity);
}
Provided solution works, but it is not strongly-typed, so it is sensible to property renaming. A strongly-typed approach can be used, but it requires some setup. However, part of the setup is so generic that it can be reused:
public class Order
{
public String OrderNo { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Misc { get; set; }
}
// clearly define properties that allow search
public enum OrderSearchableProp
{
OrderNo = 1,
FirstName = 2,
LastName = 3
}
class Program
{
// strongly-type requires an explicit mapping between property and its expression within the order object
static Dictionary<OrderSearchableProp, Expression<Func<Order, String>>> OrderSearchableMap = new Dictionary<OrderSearchableProp, Expression<Func<Order, string>>>()
{
{ OrderSearchableProp.OrderNo, o => o.OrderNo },
{ OrderSearchableProp.FirstName, o => o.FirstName },
{ OrderSearchableProp.LastName, o => o.LastName },
};
// this gets a PropertyInfo based from an Expression. It should be placed into a generic utility class
// credit goes to Daniel - http://stackoverflow.com/a/17116267/2780791
public static PropertyInfo GetPropertyFromExpression<T, TProp>(Expression<Func<T, TProp>> GetPropertyLambda)
{
MemberExpression Exp = null;
//this line is necessary, because sometimes the expression comes in as Convert(originalexpression)
if (GetPropertyLambda.Body is UnaryExpression)
{
var UnExp = (UnaryExpression)GetPropertyLambda.Body;
if (UnExp.Operand is MemberExpression)
{
Exp = (MemberExpression)UnExp.Operand;
}
else
throw new ArgumentException();
}
else if (GetPropertyLambda.Body is MemberExpression)
{
Exp = (MemberExpression)GetPropertyLambda.Body;
}
else
{
throw new ArgumentException();
}
return (PropertyInfo)Exp.Member;
}
public static IList<Order> getFilteredOrders(int propFilterValue, IList<Order> orders, String needle)
{
var filterValue = (OrderSearchableProp)propFilterValue;
var filterProp = OrderSearchableMap[filterValue];
var lowNeedle = needle?.ToLower() ?? String.Empty;
return orders.Where(o =>
{
var propInfo = GetPropertyFromExpression<Order, String>(filterProp);
var propValue = (String) propInfo.GetValue(o) ?? String.Empty;
return propValue.ToLower().Contains(lowNeedle);
}).ToList();
}
static void Main(string[] args)
{
// can be used to populate the combo items
// otherwise, not used in this example
OrderSearchableProp[] enumValues = (OrderSearchableProp[])Enum.GetValues(typeof(OrderSearchableProp));
// test orders
var orderList = new List<Order>()
{
new Order() { OrderNo = "1234ABC", FirstName = "George", LastName = "Taylor", Misc = "Extra information"},
new Order() { OrderNo = "AB10", FirstName = "Anonymous", LastName = "X", Misc = "No comment"}
};
// test OrderNo search
var searchProp = (int) OrderSearchableProp.OrderNo;
var foundOrders = getFilteredOrders(searchProp, orderList, "ABC");
// test FirstName search
searchProp = (int)OrderSearchableProp.FirstName;
foundOrders = getFilteredOrders(searchProp, orderList, "a");
// test LastName search with empty string
searchProp = (int)OrderSearchableProp.LastName;
foundOrders = getFilteredOrders(searchProp, orderList, "");
// empty return
searchProp = (int)OrderSearchableProp.OrderNo;
foundOrders = getFilteredOrders(searchProp, orderList, null);
}
}

Map a column with string representing a list to a List<> object using Dapper

I have the following model:
public class Model {
public string Name { get; set; }
public List<int> Numbers { get; set; }
}
And an SQL query that returns the following dataset containing two nvarchar columns:
Name
Numbers
foo
1,2,3,4
bar
4,17
Is there a simple way to auto-assign the results of the query to a List<Model> using Dapper?
I know I could use multi-mapping and make the splitting myself in C# code, but I would rather get a simpler solution.
I'm not sure if you can call this "simpler", but something like this is an option:
public class Result
{
public string Name { get; set; }
public List<int> Numbers { get; set; }
}
public class DapperTests
{
[Test]
public void Test()
{
var conn = new SqlConnection(#"Data Source=.\sqlexpress; Integrated Security=true; Initial Catalog=mydb");
conn.Open();
var result = conn.Query<string, string, Result>(
"select Name = 'Foo', Numbers = '1,2,3' union all select Name = 'Bar', Numbers = '4,5,6'", (a, b) => new Result
{
Name = a,
Numbers = b.Split(',').Select(Int32.Parse).ToList()
}, splitOn: "*").ToList();
Assert.That(result.Count, Is.EqualTo(2));
Assert.That(result.FirstOrDefault(x => x.Name == "Foo").Numbers.Count, Is.GreaterThan(0));
Assert.That(result.FirstOrDefault(x => x.Name == "Bar").Numbers.Count, Is.GreaterThan(0));
}
}
An alternative option with multimapping... pretty ugly
public class Result
{
public string Name { get; set; }
public List<int> NumberList { get; set; }
public string Numbers { set { NumberList = value.Split(',').Select(Int32.Parse).ToList(); } }
}
public class DapperTests
{
[Test]
public void Test()
{
var conn = new SqlConnection(#"Data Source=.\sqlexpress; Integrated Security=true; Initial Catalog=mydb");
conn.Open();
var sql = #"
select Name = 'Foo', Numbers = '1,2,3';
select Name = 'Bar', Numbers = '4,5,6';";
var expectedResults = 2;
var results = new List<Result>();
using (var multi = conn.QueryMultiple(sql))
{
for (int i = 0; i < expectedResults; i++)
{
results.Add(multi.Read<Result>().Single());
}
}
Assert.That(results.Count, Is.EqualTo(2));
Assert.That(results.FirstOrDefault(x => x.Name == "Foo").NumberList.Count, Is.GreaterThan(0));
Assert.That(results.FirstOrDefault(x => x.Name == "Bar").NumberList.Count, Is.GreaterThan(0));
}
}

BindingList<> (master) with a composed BindingList<> (child) reference

I have a situation where a BindingList<> represents a collection of POCOs that have sub-collections of similar nature, Here is a sample code of two such POCOs and their respective lists:
The DirectoryTypePoco
public class DirectoryTypePoco : IBasePoco
{
public DirectoryTypePoco()
{
}
public DirectoryTypePoco(Int16 directoryTypeId, String directoryImplementation, String directoryDescription, DirectoryDefinitionPocoList directoryDefinition)
{
DirectoryTypeId = directoryTypeId;
DirectoryImplementation = directoryImplementation;
DirectoryDescription = directoryDescription;
DirectoryDefinition = directoryDefinition;
}
public Int16 DirectoryTypeId { get; set; }
public String DirectoryImplementation { get; set; }
public String DirectoryDescription { get; set; }
public DirectoryDefinitionPocoList DirectoryDefinition { get; set; }
public object GenerateEntity(GenericRepository repository, params object[] parameters)
{
var lastMaxEntityId = repository.GetQuery<DirectoryType>().Select(select => #select.DirectoryTypeId).DefaultIfEmpty().Max();
var newEntity = new DirectoryType
{
DirectoryTypeId = (short)(lastMaxEntityId + 1),
DirectoryImplementation = this.DirectoryImplementation,
DirectoryDescription = this.DirectoryDescription
};
return newEntity;
}
}
And the BindingList<DirectoryTypePoco>:
public class DirectoryTypePocoList : BindingList<DirectoryTypePoco>
{
public DirectoryTypePocoList()
{
using (var repository = new GenericRepository(new PWRDbContext()))
{
var query = repository.GetQuery<DirectoryType>();
foreach (var r in query)
{
Add(new DirectoryTypePoco(r.DirectoryTypeId, r.DirectoryImplementation, r.DirectoryDescription, new DirectoryDefinitionPocoList(r.DirectoryTypeId)));
}
}
}
public DirectoryTypePocoList(short directoryTypeId)
{
using (var repository = new GenericRepository(new PWRDbContext()))
{
var query = repository.GetQuery<DirectoryType>(where => where.DirectoryTypeId == directoryTypeId);
foreach (var r in query)
{
Add(new DirectoryTypePoco(r.DirectoryTypeId, r.DirectoryImplementation, r.DirectoryDescription, new DirectoryDefinitionPocoList(r.DirectoryTypeId)));
}
}
}
}
The second object: DirectoryDefinitionPoco
public class DirectoryDefinitionPoco : IBasePoco
{
public DirectoryDefinitionPoco()
{
}
public DirectoryDefinitionPoco(Int16 directoryTypeId, Byte parameterId, String parameterName, String parameterValidation, Boolean encryptionRequired, PocoChangeType changeType = PocoChangeType.None)
{
DirectoryTypeId = directoryTypeId;
ParameterId = parameterId;
ParameterName = parameterName;
ParameterDescription = parameterName;
ParameterRequired = false;
ParameterValidation = parameterValidation;
EncryptionRequired = encryptionRequired;
}
public Int16 DirectoryTypeId { get; set; }
public Byte ParameterId { get; set; }
public String ParameterName { get; set; }
public String ParameterDescription { get; set; }
public String ParameterValidation { get; set; }
public Boolean ParameterRequired { get; set; }
public Boolean EncryptionRequired { get; set; }
public object GenerateEntity(GenericRepository repository, params object[] parameters)
{
var masterId = (short) parameters[0];
var lastMaxEntityId = repository.GetQuery<DirectoryDefinition>(where => where.DirectoryTypeId == masterId).Select(select => #select.ParameterId).DefaultIfEmpty().Max();
var newEntity = new DirectoryDefinition
{
DirectoryTypeId = (short)parameters[0],
ParameterId = (byte)(lastMaxEntityId + 1),
ParameterName = this.ParameterName,
ParameterDescription = this.ParameterDescription,
ParameterValidation = this.ParameterValidation,
ParameterRequired = this.ParameterRequired,
EncryptionRequired = this.EncryptionRequired
};
return newEntity;
}
}
And BindingList<DirectoryDefinitionPoco>:
public class DirectoryDefinitionPocoList : BindingList<DirectoryDefinitionPoco>
{
public DirectoryDefinitionPocoList(short directoryTypeId)
{
using (var repository = new GenericRepository(new PWRDbContext()))
{
var query = repository.GetQuery<DirectoryDefinition>(where => where.DirectoryTypeId == directoryTypeId);
foreach (var r in query)
{
Add(new DirectoryDefinitionPoco(r.DirectoryTypeId, r.ParameterId, r.ParameterName, r.ParameterValidation, r.EncryptionRequired));
}
}
}
public List<DirectoryDefinition> GetSourceQuery()
{
List<DirectoryDefinition> result;
using (var repository = new GenericRepository(new PWRDbContext()))
{
result = repository.GetQuery<DirectoryDefinition>().ToList();
}
return result;
}
public List<DirectoryDefinition> GetSourceQuery(short directoryTypeId)
{
List<DirectoryDefinition> result;
using (var repository = new GenericRepository(new PWRDbContext()))
{
result = repository.GetQuery<DirectoryDefinition>(where => where.DirectoryTypeId == directoryTypeId).ToList();
}
return result;
}
}
On the form, I load the data into the grid through a BindingSource component. The child rows are added properly and the data is valid.
Here is the issue: I'm able to add new DirectoryTypePoco but when try to add a DirectoryDefinitionPoco, in the code, the the DirectoryDefinitionPocoobject that I get has a zero for it's parent object. In the above picture, the Test5.dll234 is a DirectoryTypePoco with DirectoryTypeId = 8 and all child under it are ok except the new one I create. What am I suppose to do to make sure I have Master-Child relation in this case?
Ok. It seems that there are two thing I should have noticed in my design.
The individual child Poco needs to know the parent Poco through a reference.
The DevExpress Grid has methods that allow for retrieving the attached data to a parent row while in the child view' particular row.
The first part is straightforwards: add a new property in the child poco of parent poco type.
This however, in my case, doesn't solve my issue as when I visually add a new row on the grid, the default constructor is invoked and it takes no parameters and hence the parent poco reference will remain NULL and the Ids (numeric) will be defaulted to 0
The second point helped fix my issue completely. I was able to conjure up an extension method for the XtraGrid's GridView as follows:
public static class DevExpressGridHelper
{
public static IBasePoco GetPocoFromSelectedRow(this BaseView view)
{
return (IBasePoco)view.GetRow(((GridView)view).FocusedRowHandle);
}
public static IBasePoco GetParentPocoFromSelectedRow(this GridView view)
{
if (view.ParentView !=null)
{
// return (IBasePoco)(view.ParentView).GetRow(((GridView)(view.ParentView)).FocusedRowHandle);
return (IBasePoco)((GridView)view.ParentView).GetFocusedRow();
}
return null;
}
}
And used it as follows:
private void GridMain_Level_1_RowUpdated(object sender, RowObjectEventArgs e)
{
var view = sender as GridView;
if (view == null)
{
return;
}
var pocoObject = e.Row as DirectoryDefinitionPoco;
if (pocoObject == null)
{
return;
}
var parentPocoObject = view.GetParentPocoFromSelectedRow();
if (parentPocoObject == null)
{
return;
}
if (view.IsNewItemRow(e.RowHandle))
{
Create(pocoObject, parentPocoObject);
}
else
{
Update(pocoObject);
}
}

Fill data in ObservableCollection using LINQ

I have a structure as below.
public class CategoryClass
{
public decimal Category_ID { get; set; }
public string Category_Name { get; set; }
//public System.Nullable<char> _Category_Type;
public ObservableCollection<DAL.SubCategoryClass> SubCat { get; set; }
}
public class SubCategoryClass
{
public decimal Sub_Category_ID { get; set; }
public string Sub_Category_Name { get; set; }
public decimal Category_ID { get; set; }
}
I need to fill data using LINQ.
I have some code here, please correct me to solve it.
public ObservableCollection<DAL.CategoryClass> GetCategoryandSubCategory()
{
var cat = from c in dbc.Categories
select new DAL.CategoryClass
{
Category_ID = c.Category_ID,
Category_Name = c.Category_Name,
SubCat = from d in dbc.Sub_Categories
where d.Category_ID == c.Category_ID
select new DAL.SubCategoryClass
{
Sub_Category_ID = d.Sub_Category_ID,
Sub_Category_Name = d.Sub_Category_Name,
Category_ID = d.Category_ID
}
};
}
Also suggest me some examples of validation tech in WPF.
One option is to just return an IEnumerable.
That may serve your needs.
If you need an ObservableCollection then you need to new it.
For List just .ToList()
As for validation one question at time.
Start with searching MSDB for validation.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
System.Diagnostics.Debug.WriteLine(OCint.Count.ToString());
}
List<SimpleClass> baseList = new List<SimpleClass> { new SimpleClass(1), new SimpleClass(2), new SimpleClass(3) };
public IEnumerable<SimpleClass> iEint
{
get { return baseList.Where(x => x.ID < 3).Select(w=> new SimpleClass(w.ID)); }
}
public List<SimpleClass> Lint
{
get { return iEint.ToList(); ; }
}
public ObservableCollection<SimpleClass> OCint
{
get { return new ObservableCollection<SimpleClass>(iEint); }
}
}
public class SimpleClass
{
public Int32 ID { get; private set; }
public SimpleClass ( Int32 id) { ID = id; }
}
public IEnumerable<DAL.CategoryClass> GetCategoryandSubCategory()
{
ObservableCollection<DAL.SubCategoryClass> s = new ObservableCollection<DAL.SubCategoryClass>();
var cat = from c in dbc.Categories
select new DAL.CategoryClass
{
Category_ID = c.Category_ID,
Category_Name = c.Category_Name,
SubCat =s.Add( from d in dbc.Sub_Categories
where d.Category_ID == c.Category_ID
select new DAL.SubCategoryClass
{
Sub_Category_ID = d.Sub_Category_ID,
Sub_Category_Name = d.Sub_Category_Name,
Category_ID = d.Category_ID
}
};).ToList()
return cat ;
}
hope it work with u
If you want GetCategoryandSubCategory() returns ObservableCollection that is refreshed automatically when dbc.Categories changes or CategoryClass (SubCotegory) properties change, you can use my ObservableComputations library. Using that library you can code:
public ObservableCollection<DAL.CategoryClass> GetCategoryandSubCategory()
{
var cat = dbc.Categories.Selecting(c =>
new DAL.CategoryClass
{
Category_ID = c.Category_ID,
Category_Name = c.Category_Name,
SubCat = dbc.Sub_Categories
.Filtering(d => d.Category_ID == c.Category_ID)
.Selecting(d => new DAL.SubCategoryClass
{
Sub_Category_ID = d.Sub_Category_ID,
Sub_Category_Name = d.Sub_Category_Name,
Category_ID = d.Category_ID
})
});
}
To make code above working dbc.Categories and dbc.Sub_Categories must be of type ObservableCollection and all the classes mentioned in the code must implement INotifyPropertyChanged.

Resources