I have two datatables. One is a superset of another. Both have one column StageID common. I need to merge these two tables together so that the subset datatables data gets stored in the correct row of superset table.
This is what i did to join the data after retrieving the superset data in JoinTable and subset data in DTMaterialProperties table
foreach (DataColumn dcMaterialProp in dtMaterialProperties.Columns)
{
if (dcMaterialProp.ColumnName != "StageId" &&
JoinDataTable.Columns.Contains(dcMaterialProp.ColumnName))
{
JoinDataTable.Rows[rowCount][dcMaterialProp.ColumnName] =
dtMaterialProperties.Rows[0][dcMaterialProp.ColumnName];
}
}
But this was not efficient as it takes a lot of time in looping through.
Please Help me in finding a better way to do this.
If you can use LINQ, an easy way would be to use the Join extension method.
See Join Method-Based Query Syntax Examples (LINQ to DataSet)
If you don't have access to LINQ to DataSet
...you can check out this link from MSDN on how to implement a DataSet JOIN Helper Class.
HOW TO: Implement a DataSet JOIN helper class is Visual C# .NET
What you are really looking for seems to be a relationship. If you add both datatables to the same dataset, you can define the relationship. See Define a relationship between two tables in a DataSet in VB .NET
Then, all you have to do is parentRow.GetChildRows() to get the associated child rows.
Related
I have two datatables with identical schemas, business partners and addresses. I'm trying to combine them in a specific format in order to import into another system.
Basically, I want the output to be as follows:
Business Partner
All associated addresses
Next business partner
All associated addresses
Here is the latest code I'm trying:
var finalDt = BpDt.Clone();
foreach(DataRow BpRow in BpDt.Rows)
{
finalDt.ImportRow(BpRow);
foreach(DataRow AddressRow in AddressDt.Rows)
{
if(Convert.ToString(BpRow["id"]).Equals(Convert.ToString(BpRow["id"])))
finalDt.ImportRow(AddressRow);
}
}
It seems to get caught in a infinite loop but I don't understand why. Is there a better way to approach this?
Your approach to this is terrible. But if you insist on going down this road, this should work:
var finalDt = BpDt.Clone();
foreach(DataRow BpRow in BpDt.Rows)
{
finalDt.ImportRow(BpRow);
foreach(DataRow AddressRow in AddressDt.Rows)
{
if(Convert.ToString(BpRow["id"]).Equals(Convert.ToString(AddressRow["id"])))
finalDt.ImportRow(AddressRow);
}
}
it seems like...
if(Convert.ToString(BpRow["id"]).Equals(Convert.ToString(BpRow["id"])))
will always be true. So you would just be inserting every AddressRow for each BpRow. Depending on your dataset size, this could be taking a really long time. Should the id comparison be this?
if(Convert.ToString(AddressRow["id"]).Equals(Convert.ToString(BpRow["id"])))
Conceptually this would be similar to a join on the id field.
A better approach might be to use LINQ. If you use the AsEnumerable() extension for DataTable you could query AddressDt using LINQ...
LINQ query on a DataTable
I have several references in DB with same table structure.
I don't want to write several LINQ queries to each db. Is it possible to develop one query with dynamic Table parameter?
My query example:
var query =
from myTranslations in myContext.translations
where myTranslations.code == strLabelCode
select myTranslations;
No, sorry. Simple like that - only via for example reflection, which makes it - ah - hard er than having multiple table objects.
Use datacontext GetTable() method to vary table type as listed here MSDN
I believe the answer to this question may be to use Linq to Sql, but wanted to see if this is something which is possible using QueryExpressions:-
I create a query expression which queries against Entity A, it also links to Entity B (via LinkEntity) and imposes additional criteria. It is possible to retrieve columns from Entity B by adding the appropriate attribute names. However, it will only retrieve the linked entity (inner join).
Is it possible using QueryExpression to retrieve all related records (and required columns) from Entity B related to Entity A (e.g. all cases associated with contact where contact passes specified criteria). Normally I would consider inverting the query and searching for Entity B relatig to Entity A with the appropriate LinkEntity Conditions, but there are a number of linked entities which I would like to retrieve for the same contact query.
So I'm left with some options:-
(1) Perform a second query (not ideal when iterating over a large number of results from the initial query),
(2) Perform a query using Linq to CRM on the filtered views,
(3) A different method entirely?
Any thoughts would be appreciated.
EDIT:
I ended up using Linq-to-Sql to complete this task and the code used is similar to that below (albeit with a few more joins for the actual query!):-
var dataCollection = (from eA in xrmServiceContext.EntityASet
join eB in xrmServiceContext.EntityBSet on new EntityReference(EntityA.EntityLogicalName, eA.Id) equals (EntityReference)eB.EntityBLookupToEntityA
select new
{
Id = eA.Id,
EntityBInterestingAttribute = eB.InterestingAttributeName
}
So this will bring back a row per Entity A, per Entity B. To make things easier I then defined a custom class "MyEntityAClass" which had properties which were Lists so I could return one object for filling of GridView etc. This is more to do with the processing of these results though so I haven't posted that code here.
I hope that makes sense. Essentially, it is getting the multiple rows per record a la SQL which makes this method work.
QueryExpression can only return fields from one type of entity, the one specified in QueryExpression.EntityName.
You can use FetchXML which allows you to also get the fields of any link entities, which would be an option 3 for you, unfortunately it returns the data as XML which you would then have to parse yourself.
It might be quicker to run the FetchXML, but it will take longet to write and test, and its not the easiest thing to maintain either.
Sample Code, this gets the first 101 of all Cases that are active for all accounts that are active
string fetch = "<fetch count='101' mapping='logical'><entity name='account'><filter type='and'><condition attribute='statecode' operator='eq' value='1'/></filter><link-entity name='incident' from='customerid' to='accountid'><all-attributes/><filter type='and'><condition attribute='statecode' operator='eq' value='1'/></filter></link-entity></entity></fetch>";
string data = yourCrmServiceObject.Fetch(fetch);
I have an organization chart tree structure stored in a database.
Is is something like
ID (int);
Name (String);
ParentID (int)
In C# it is represented by a class like
class Employee
{
int ID,
string Name,
IList < Employee> Subs
}
I am wondering how is the best way to retrieve these values from the database to fill up the C# Objects using LINQ (I am using Entity Framework)
There must be something better than making a call to get the top level then making repeated calls to get subs and so on.
How best to do it?
You can build a stored proc that has built in recursion. Take a look at http://msdn.microsoft.com/en-us/library/ms190766.aspx for more info on Common Table Expressions in SQL Server
You might want to find a different (better?) way to model your data. http://www.sqlteam.com/article/more-trees-hierarchies-in-sql lists a popular way of modeling hierarchical data in a database. Changing the modeling can allow you to create queries that can be expressed without recursion.
If you're using SQL Server 2008, you could make use of the new HIERARCHYID feature.
Organizations have struggled in past
with the representation of tree like
structures in the databases, lot of
joins lots of complex logic goes into
the place, whether it is organization
hierarchy or defining a BOM (Bill of
Materials) where one finished product
is dependent on another semi finished
materials / kit items and these kit
items are dependent on another semi
finished items or raw materials.
SQL Server 2008 has the solution to
the problem where we store the entire
hierarchy in the data type
HierarchyID. HierarchyID is a variable
length system data type. HierarchyID
is used to locate the position in the
hierarchy of the element like Scott is
the CEO and Mark as well as Ravi
reports to Scott and Ben and Laura
report to Mark, Vijay, James and Frank
report to Ravi.
So use the new functions available, and simply return the data you need without using LINQ. The drawback is you'll need to use UDF or stored procedures for anything beyond a simple root query:
SELECT #Manager = CAST('/1/' AS hierarchyid)
SELECT #FirstChild = #Manager.GetDescendant(NULL,NULL)
I'd add a field to the entity to include the parent ID, then I'd pull the whole table into memory leaving the List subs null. Id then iterate through the objects and populate the list using linq to objects. Only one DB query so should be reasonable.
An Entity Framework query should allow you to include related entity sets, though in a unary relationship, not sure how it would work...
Check this out for more information on that: http://msdn.microsoft.com/en-us/library/bb896272.aspx
Well... even with LINQ you will need two queries, because any single query will duplicate the main employee and thus will result in multiple employees (that are really the same) being created... However, you can hide this a bit with linq when you create the object, that's when you would execute the second query, something like this:
var v = from u in TblUsers
select new {
SupervisorName = u.DisplayName,
Subs = (from sub in TblUsers where sub.SupervisorID.Value==u.UserID select sub.DisplayName).ToList()
};
How do you get a list of all the tables and use that list to enumerate the columns?
I've found posts that describe one or the other, but not both.
My net-result is I want to generate a static class which contains names of all the columns in each tables so I could, for example, do:
comboBoxFoo.DisplayMember = SomeNamespace.SomeTable.SomeDisplayColumnName;
comboBoxFoo.ValueMember = SomeNamespace.SomeTable.SomeIDColumnName;
comboBoxFoo.DataSource = dingo;
I'm currently using this method which while it works, it means I have to manually create my tables in a list.
I have a seperate command line project which generates the SomeNameSpace.SomeTable class manually and I add the generated class file in to the project.
Ideally, if I could loop through via a foreach of tables and do something like this:
foreach(var table in someTableNumerationMethodForAGivenContext())
{
var columnList = databaseContext.ColumnNames<someTable>();
foreach(var columnData in columnList)
{
DoJazz(columnData.Name);
}
}
Is there a better way to do this other than manually have to do the databaseContext.ColumnNames() ?
Edit 1:
We're using LinqToSQL. Moving to ADO.NET also an option on the table, but at the moment we have no pressing need to.
Edit 2:
I know L2S does databinding but what I'm after is getting a list of column names as strings from a table. L2S doesn't offer this or it's not apparent on my side.
I'd like to do something like: SomeTable.SomeColumn.ToString() or something. SubSonic has this.
Final:
Thanks everyone. all are very good answers and lead me to the answer. You guys rock!
Nazadus,
Is this what you are looking for?
LINQ to SQL Trick: Get all Table [and Column] Names:
http://blogs.msdn.com/jomo_fisher/archive/2007/07/30/linq-to-sql-trick-get-all-table-names.aspx
What you are describing is essentially an ORM
Linq to SQL is an ORM that will create prototype c# classes for you that contain the information you are describing. It has excellent support for the kind of data binding that you have illustrated.
I think you are looking for this.
DataContext.Mapping.GetTable(yourTable).RowType.DataMemebers()
I can think of two ways to do this.
A) Use SMO to get all the tables / columns in a database. You need to reference:
Microsoft.SqlServer.ConnectionInfo
Microsoft.SqlServer.Management.Sdk.Sfc
Microsoft.SqlServer.Smo
Then, you can do something like this:
ServerConnection connection = new ServerConnection(".");
Server server = new Server(connection);
Database db = server.Databases["Northwind"];
foreach (Table table in db.Tables)
{
foreach (Column column in table.Columns)
{
Console.WriteLine("Table: {0}, Column: {1}",table.Name,column.Name);
}
}
}
B) Use reflection to reflect over your assembly with the dataclasses generated by Linq to Sql. Anything with a Table attribute is a table, and anything with a Column attribute is a column. Let me know if you need a sample...