Getting Missing Rows inside a table and copy them to another table - c#

var FileProducts = from ProductsRow in ProductRangesDt.AsEnumerable()
join Filee in FileTb.AsEnumerable() on ProductsRow["GEN_CODE"].ToString() equals Filee["GEN_CODE"].ToString()
select new
{
PRODUCT_ID = ProductsRow["PRODUCT_ID"],
PRODUCT_NAME = ProductsRow["PRODUCT_NAME"],
PROVIDER_ID = ProductsRow["PROVIDER_ID"],
PROVIDER_NAME = ProductsRow["PROVIDER_NAME"],
GEN_CODE = ProductsRow["GEN_CODE"],
MIN_QUANTITY = Filee["MIN_QUANTITY"],
MAX_QUANTITY = Filee["MAX_QUANTITY"],
DISCOUNT_VALUE = Filee["DISCOUNT_VALUE"]
};
var s = (from b in FileProducts
select b.PRODUCT_ID).Distinct(); // count=285
var Products = (from ProductsRow in ProductRangesDt.AsEnumerable()
select ProductsRow["PRODUCT_ID"]).Distinct(); // count=7159
var result = Products.Except(s); // it's count should be 7159-285
I want to get all the products ID that are in Products and don't exist in FileProducts how can i do this ? result always return 0 as count

From the MSDN documentation about Except extension method:
This method is implemented by using deferred execution. The immediate
return value is an object that stores all the information that is
required to perform the action. The query represented by this method
is not executed until the object is enumerated either by calling its
GetEnumerator method directly or by using foreach in Visual C# or For
Each in Visual Basic.
So in order to get the real value form your Set differentiation, you need to enumerate your result either by a call to the Count()-Method (result.Count()) on using foreach (foreach (var r in result) { ... }).
I can't test with your data, but with test data at my disposition, the Except-extension did delivered the correct results.

Related

How set OrderBy on GroupedEnumerable

My result set is not sorting. How do I set up OrderBy for type System.Linq.GroupedEnumerable
I've converted an application from Core 1.1 to 2.2. Everything ported over fine except one piece of logic that:
1) takes a response from a service call maps it to a GroupedEnumerable
2) takes the grouped set and passes it to a function that maps it to an object of type System.Linq.Enumerable.SelectEnumerableIterator.
The resulting object is properly populated but not sorted. I have tried the order by in the function parameter call and as a separate process afterwards.
//response = {myService.myClient.SearchNominationsResponse}
//groupedSet = {System.Linq.GroupedEnumerable<ServiceClients.myClient.NominationObject, long>}
//result = {System.Linq.Enumerable.SelectEnumerableIterator<System.Linq.IGrouping<long, ServiceClients.myClient.NominationObject>, app.ViewModels.EvaluationSummary>}
public IEnumerable<EvaluationSummary> GetEvaluationSummaries(string sortBy, string sortOrder, Filter filter = null)
{
var request = Mapper.MapSearchNominationRequest(filter);
request.IsDetailed = false;
var response = myService.SearchNominationsAsync(request).GetAwaiter().GetResult();
var groupedSet = response.mySet.GroupBy(n => n.SetId);
// I get a proper result but it is not sorted
var result = groupedSet.Select(
g => Mapper.MapEvaluationSummary(
g.OrderBy(g2 => sortBy + " " + sortOrder)
.Last()));
// Still not sorting
result = result.OrderBy(r => sortBy + sortOrder);
return result;
}
public EvaluationSummary MapEvaluationSummary(SetObject setIn)
{
var eval = new EvaluationSummary
{
setDate = setIn.Date,
setId = setIn.Id,
setTypeId = setIn.TypeId,
setTypeDescription = setIn.TypeDescription,
setStatusId = setIn.StatusId,
setStatusDescription = setIn.StatusDescription,
setBy = setIn.Manager,
setEmployee = setIn.employee
};
}
So in my view I have columns that list Date, Id, setEmployee. I can click on these values to issue a sort pattern and I can see that the sortBy and sortOrder variables are being passed in with proper values but the sorting is not happening.
I expect 'William' to appear before 'Bill' and then Bill to appear before 'William' when toggling the employee column header in my view.
Based off of the previous answers, I'm still not sure if I can substitute a property name in the LINQ with a variable. To fix my problem and move on I've implemented JS logic to sort my table headers. We had a custom JS that we use to format tables in our apps but it seems the sort functionality never worked. Anyway not an answer to my question but this is how I solved the problem:
Logic can be found at:
http://www.kryogenix.org/code/browser/sorttable/
-HaYen

Foreach updates every record in a LINQ result

I use a WCF Data Service to get data using pagination.
I have to provide a specific object (ExtraData) for the clients, but in the database, there is no such data. It is a combined data of a few tables and it has 1 row to make it cross-joinable.
As WCF Data Services does not allow dynamic object creation, the returned data must be inside the query.
The service return the updated data in the form what the clients require.
I have the following method:
[WebGet]
public IQueryable<ExtraData> GetExtraData(string groupID)
{
var query= (from data in context.Data
join information in context.Information on information.ID equals data.InformationID into tempInformation
from information in tempInformation.DefaultIfEmpty()
from extraData in context.ExtraData // cross-joining the dummy
where data.GroupID == groupID
select new
{
ExtraData = extraData,
Data = data,
InformationText = information.Text
}).ToList();
//After the execution, I intend to modify the result (as it is a dummy record yet):
query.ForEach(
item =>
{
item.ExtraData.DataID = item.Data.ID;
item.ExtraData.Name = item.Data.NameAux;
item.ExtraData.Group = elem.Data.ExtraGroup;
}
);
return (from item in query
select item.ExtraData).AsQueryable();
}
Unfortunately, it modifies every record each time, so I end up having the same record multiple times.
What should I modify to make the ExtraData records unique?
UPDATE:
Inside the foreach, I get this data:
3ca65876-c88f-4849-bef5-170e62f084ec Name16
b705ebc3-8245-4c16-8045-a79ef15192d2 Name16
b8bb423c-02ff-4e9a-b941-a20a9c69dd12 Name Second 16
4e3d3496-4b36-4dab-b471-a43ffb075345 Other16
f93a2358-818e-4929-a51a-46a7b7080bd4 Test16
a4bca994-73d2-4d0e-a18a-2539067a7498 Test Second 16
c7474a92-430a-46ad-bc3d-7e526dfb2647 New Test 16
6117f1b6-3f6b-4fae-b448-2778d68d0877 New Test Mod 16
8e831455-4305-4ee3-b56d-3b0e23131df8 Test Mod 16
In the result set, I get this:
<entry><id>http://localhost/MyService/Service.svc/ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')</id><category term="ExtraData" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" title="ExtraData" href="ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')" /><title /><updated>2015-11-10T10:07:36Z</updated><author><name /></author><content type="application/xml"><m:properties><d:ID m:type="Edm.Guid">8e831455-4305-4ee3-b56d-3b0e23131df8</d:ID><d:Name>Test Mod 16</d:Name><d:Group m:type="Edm.Int32">1</d:Group></m:properties></content></entry>
<entry><id>http://localhost/MyService/Service.svc/ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')</id><category term="ExtraData" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" title="DSPaciens" href="ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')" /><title /><updated>2015-11-10T10:07:36Z</updated><author><name /></author><content type="application/xml"><m:properties><d:ID m:type="Edm.Guid">8e831455-4305-4ee3-b56d-3b0e23131df8</d:ID><d:Name>Test Mod 16</d:Name><d:Group m:type="Edm.Int32">1</d:Group></m:properties></content></entry>
Well, we were very close to the solution :)
The key element was what #usr wrote:
There's just one such object per row in the database. You're writing
the the same objects many times.
Unfortunately, the selected anonymous object are read-only, so I had to create a wrapper-class that holds the necessary data:
public class CombinedData
{
public ExtraData ExtraData { get; set; }
public Data Data { get; set; }
public string InformationText {get; set; }
}
Then use it inside the query:
var query= (from data in context.Data
join information in context.Information on information.ID equals data.InformationID into tempInformation
from information in tempInformation.DefaultIfEmpty()
from extraData in context.ExtraData // cross-joining the dummy
where data.GroupID == groupID
select new CombinedData
{
ExtraData = extraData,
Data = data,
InformationText = information.Text
}).ToList();
Then create a new ExtraData object inside the ForEach loop:
query.ForEach(
item =>
{
item.ExtraData=new ExtraData();
item.ExtraData.DataID = item.Data.ID;
item.ExtraData.Name = item.Data.NameAux;
item.ExtraData.Group = elem.Data.ExtraGroup;
}
);
Now, it works. Thanks for pointing me to the right direction :)

Building a Dynamic Linq Query using Equals and an Array

I have been trying to solve the syntax for a dynamic linq query that is needed in my application.
I have a dynamic query that the where clause needs to be specified to either
GuidPrimaryKey is contained in a list of Guid OR
GuidPrimaryKey is equal to an item in a list of Guid (using some type of for-loop)
I have a Guid[] populated with over 5,000 keys. My Query is set up as
If I do this (as a test) it is successful
data = data.where("GuidPrimaryKey.Equals(#0)",array[0]);
as well as
data = data.where("GuidPrimaryKey.Equals(#0) OR GuidPrimaryKey.Equals(#1)",array[0], array[1]);
I have tried:data = data.where("GuidPrimaryKey.Contains(#0)",array); but that gives an error: No applicable method 'Contains' exists in type 'Guid'.
I also tried setting a loop to go through the elements in the array and set the where clause as a giant string, but that did not work either.
string s = "";
string p = ""
int counter = 0;
foreach(Guid g in Array)
{
s+= "GuidPrimaryKey.Equals(#" counter.ToString() + ") OR";
p += "Array[" counter.ToString() + "],";
counter++;
}
s = s.remove(s.length - 3, 3);
p = p.remove(p.length - 1, 1);
data = data.Where(s,p);
This gives me the error message: No Property or field '1' exists in type 'DynamicClass1'
Any ideas? I need to have the where clause build the query to check to see if the primary key (GuidPrimaryKey) exists in the list of keys (Guid[]).
I'm not sure if this works in the standard Dynamic Linq library, but I just tried this is my open-source version, and it works well:
var data = data.Where("GuidPrimaryKey in #0", array);
This also works:
var data = data.Where("#0.Contains(GuidPrimaryKey)", array);
Here is a full unit test I wrote to confirm this:
[TestMethod]
public void ExpressionTests_ContainsGuid()
{
//Arrange
//Generate some users with Id fields of type Guid
var userList = User.GenerateSampleModels(5, false);
var userQry = userList.AsQueryable();
//Generate a list of values that will fail.
var failValues = new List<Guid>() {
new Guid("{22222222-7651-4045-962A-3D44DEE71398}"),
new Guid("{33333333-8F80-4497-9125-C96DEE23037D}"),
new Guid("{44444444-E32D-4DE1-8F1C-A144C2B0424D}")
};
//Add a valid Guid so that this list will succeed.
var successValues = failValues.Concat(new[] { userList[0].Id }).ToArray();
//Act
var found1 = userQry.Where("Id in #0", successValues);
var found2 = userQry.Where("#0.Contains(Id)", successValues);
var notFound1 = userQry.Where("Id in #0", failValues);
var notFound2 = userQry.Where("#0.Contains(Id)", failValues);
//Assert
Assert.AreEqual(userList[0].Id, found1.Single().Id);
Assert.AreEqual(userList[0].Id, found2.Single().Id);
Assert.IsFalse(notFound1.Any());
Assert.IsFalse(notFound2.Any());
}

how to convert int to string in Linq to entities

My Db column in a string (varchar) and i need to assign it to a int value.
I am using linq to query.Though the code compiles am getting an error at the run time .
Thanks in advance.
PFB my query :
var vlauesCap = from plan in entities.PA_RTM_CAP_Group
select new Business.PartnerProfile.LookUp
{
Id =Convert.ToInt32(plan.cap_group_code),
//(Int32)plan.cap_group_code,
Value = plan.cap_group_name
};
return vlauesCap.ToList();
The EF provider does not know how to translate Convert.ToInt() into SQL it can run against the database. Instead of doing the conversion on the server, you can pull the results back and do the conversion using linq to objects:
// the ToList() here causes the query to be executed on the server and
// the results are returned in a list of anonymous objects
var results = (from plan in entities.PA_RTM_CAP_Group
select new
{
Code = plan.cap_group_code,
Name = plan.cap_group_name
}).ToList();
// the conversion can now be done here using Linq to Objects
var vlauesCap = from r in results
select new Business.PartnerProfile.LookUp
{
Id = Convert.ToInt32(r.Code),
Value = r.Name
};
return vlauesCap.ToList();
You can't do this directly, what you can do is declare a private variable to handle your "mapped" value, and expose the unmapped property...
[Column(Name = "cap_group_code", Storage = "m_cap_group_code")]
private string m_cap_group_code;
public int cap_group_code {
get
{
return Int32.Parse(m_cap_group_code);
}
set
{
m_cap_group_code = value.ToString();
}
}
Try this:
var vlauesCap = from plan in entities.PA_RTM_CAP_Group
select new Business.PartnerProfile.LookUp
{
Id =Convert.ToInt32(plan.cap_group_code),
Convert.ToInt32(plan.cap_group_code),
Value = plan.cap_group_name
};
return vlauesCap.ToList();
Why aren't you using casting for such a purpose, which is a more effective way of achieving this.
Just replace Convert.ToInt32(plan.cap_group_code) with (int)plan.cap_group_code
Do remember, there should be a value in the string and is int, else it will show Exception. If you are not sure about it, then you can further expand the casting to use null coalesciting operator

Linq getting child items

When I do a lunq query on an EF model, does it not get child entities we well? I have a Transaction table, which has link to a Payee, and a transaction type entity. Also, each transaction has a list of transaction lines...
But the code bellow - all the child objects seen to be NULL, yet the data in the actual entity (Date) seems OK. But in the line: t.account.account_id; .... 'account' is NULL.
public static List<AccountTransactionDto> GetTransaction()
{
var trans = (from t in Db.account_transaction
select t).ToList();
List<AccountTransactionDto> al = new List<AccountTransactionDto>();
foreach(var t in trans)
{
AccountTransactionDto a = new AccountTransactionDto();
a.AccountId = t.account.account_id;
a.AccountTransactionId = t.account_transaction_id;
a.PayeeId = t.payee.payee_id;
a.TransactionDate = t.transaction_date;
a.TransactionTypeId = t.z_transaction_type.transaction_type_id;
foreach(var tl in t.account_transaction_line)
{
AccountTransactionLineDto l = new AccountTransactionLineDto();
l.AccountTransactionLineId = tl.account_transaction_line_id;
l.Amount = tl.amount;
l.BudgetId = tl.budget.budget_id;
l.CostCenterId = tl.cost_centre.cost_centre_id;
l.SubCategoryId = tl.sub_category.sub_category_id;
a.AccountTransactionLine.Add(l);
}
al.Add(a);
}
return al;
}
You have two options. You can enable the Lazy Loading via:
Db.ContextOptions.LazyLoadingEnabled = true;
Or if you change the query line to this (exact syntax may not be correct for Include):
var trans = (from t in Db.account_transaction
select t).Include("account_transaction.account_transaction_line");
Then it should pull back the child records with the parent record in a single result set. But this has performance penalties if there is a great amount of data.
Lazy loading needs to be enabled on your data context.
Db.ContextOptions.LazyLoadingEnabled = true;
or you need to explicitly tell EF to load the association. i.e.
var trans = (from t in Db.account_transaction.Include('account').Include('payee') select t).ToList();

Categories