I've been trying to parse an excel file using the LinqToExcel library. My excel file has the following "design":
Property1 | Property2 | HasExtraProperty1 | HasExtraProperty2 | HasExtraProperty3
------------|---------------|-----------------------|-----------------------|-------------------
foo | bar | yes | yes | no
barfoo | foobar | no | no | yes
barbar | foofoo | no | yes | no
An abstraction of my model looks like this:
class MyModel
{
List<ExtraProperties> extraProperties;
String property1;
String property2;
}
I used the mappings from the library to easily map the (in this example) String properties to the columns. This all works fluently, but now I'm stuck parsing the other properties. Only the the extra properties with a "yes" should be added to the list. Any ideas on how to solve this with a linq query?
Note 1: For future-proofness, the number of extra properties should be able to vary.
Note 2: I've considered using another library, but I'm already using LinqToExcel somewhere in my project, and I'm trying to keep the dependencies at a minimum.
Seems like the easiest solution was to abandon the convenient mapping provided by LinqToExcel, and just looping through every columnname/row.
IExcelQueryFactory fact = new ExcelQueryFactory(path);
var query = from r in fact.Worksheet(0)
select r;
IList<MyModel> models = new List<MyModel>();
foreach(var row in query){
MyModel m = new MyModel();
foreach(String colName in MyColMapping.Keys){
p.GetType().GetProperty(colName).SetValue(p, row[ColMapping[colName]]);
}
foreach(ExtraProperty p in PMapping.Keys){
if(row[PMapping[p]].Equals("yes"))
m.ExtraProperties.Add(p);
}
models.add(m);
}
Note: ColMapping is a dictionary which maps names of excel-columns with model-properties. PMapping is a dictionary which maps excel-columns with the right object of the extra properties.
Related
In EF Core how can I efficiently check if text column of Json array contains any number from passed integer array using LINQ?
Example of table, where Id is integer type and Name and TypeJson are text
| Id | Name | TypeJson |
| --- | ---------- | -------- |
| 1 | Name One | [1,2] |
| 2 | Name Two | [2,3] |
| 3 | Name Three | [4,7] |
In Postgresql I would have written something like this
SELECT *
FROM "Table"
WHERE translate("TypeJson", '[]','{}')::int[] && ARRAY[1, 7]
where the select would return 1 and 3 rows.
I'd like to achieve same result by using LINQ functions.
I tried using EF.Functions but didn't achieve much. My attempt
await _dbContect.Table
.Where(x => !string.IsNullOrEmpty(x.TypeJson ) &&
EF.Functions.JsonContains(x.TypeJson , "[1]")
.ToListAsync();
But it produces error as column is type of text and not Json
System.InvalidOperationException: The EF JSON methods require a JSON parameter and none was found.
The entity:
public class Table
{
public int Id { get; set; }
public string Name { get; set; }
public string TypeJson { get; set; }
}
Using FromSqlRaw() is not possible because there is already written code and would be preferable if I didn't have to rewrite whole code block.
As I found out my code had three main problems
await _dbContect.Table
.Where(x => !string.IsNullOrEmpty(x.TypeJson) &&
EF.Functions.JsonContains(x.TypeJson , "[1]")
.ToListAsync();
First of all I was using EF.Functions.JsonContains() function on
text column which is not valid, json functions are deliberately
written for jsonb type.
After altering column type to jsonb, the
second problem was using string function to check if jsonb column
was null or empty which doesn't make sense and produces exception. Link to github issue
The third problem was the parameter I tried to filter with "[1]", integer needs to be passed as a JsonElement JsonSerializer.SerializeToElement(value); Link to github issue by ahanusa
Credits to #GuruStron for directing me to correct direction
I am using the FitNesse / FitSharp (c#) for testing purposes.
I can create normal fixture like ColumnFixtures, RowFixtures, DoFixtures etc. but not I am looking for a way to read columns and bind them dynamically.
The reason for this is, I still already have a huge amount of Pojo objects in my own library and don't want to repeat all class members again. Therefor i am searching for a way to handle column dynamically.
e.g.
!|Create| pojoType | record | pojoName |
|Name | LastName | Address| Misc |
| a | b | c | d |
public class DynamicHandling : DoFixture () {
public void CreateRecord(string type, string name) {
var clazz = GetClazzOfType();
var headers = GetHeadersOfColumn();
var values = GetValuesOfColumn();
var pojo = DoBindingAndAssignValues(headers, rows, clazz);
// ... Continue with whatever e.g. ...
var name = pojo.Name;
var lastName = pojo.LastName;
var address = pojo.Address;
address.split(';') ...
}
}
Any idea ?
Take a look at the source code for the Compute fixture (https://fitsharp.github.io/Fit/ComputeFixture.html) and see if it helps.
You can write a fixture that processes cells dynamically like this:
public class MyFixture: Interpreter {
public void Interpret(CellProcessor processor, Tree<Cell> table) {
new Traverse<Cell>()
.Rows.Header(row => FunctionThatDoesSomethingWithTheHeaderRow(row))
.Rows.Rest(row => FunctionThatDoesSomethingWithEachSubsequentRow(row))
.VisitTable(table);
}
...
}
There's other sets of rows you can traverse - check out the Traverse source code.
I'm trying to query an Oracle DB (version 11.2.0.2.0) in a project that uses ADO.NET, compiled at .NET 4 (I would compile at .NET 4.5 if Windows XP was compatible with it), and uses linq to entities to perform the query. I'm also using Oracle Developer Tools for Visual Studio and ODP.NET version 11.2.0.3.20. However, whenever the query is performed in the application, I get back a list of objects with incorrect data. What I mean by incorrect data is this: I have 5 properties in the entity object and two of those properties are not set as entity keys. The two properties that ARE NOT set as entity keys contain the same data for all records returned...but when I manually do a query on the DB with a DB query client, I get different values in those columns for each record!
Here's the auto generated code that I'm getting (using DBContext but I've verified that this happens with ObjectContext too):
public partial class EntityObj
{
public string EntityKey1 { get; set; }
public string EntityKey2 { get; set; }
public string EntityKey3 { get; set; }
public Nullable<decimal> NonEntityKey1 { get; set; }
public string NonEntityKey2 { get; set; }
}
Here's my linq to entities code:
using (Entities context = new Entities())
{
string formattedStr = Decimal.Parse(str).ToString();
var objs = (from obj in context.EntityObjs
where obj.Number == formattedStr
orderby obj.EntityKey3 , obj.NonEntityKey2, obj.NonEntityKey1
select obj);
// Process results...
}
Here is an example of the result set that I get when I manually do the query:
| EntityKey1 | EntityKey2 | EntityKey3 | NonEntityKey1 | NonEntityKey2 |
----------------------------------------------------------------------------------
| Val1.1 | Val1.2 | Val1.3 | 1 | Val1.4 |
----------------------------------------------------------------------------------
| Val2.1 | Val2.2 | Val2.3 | 2 | Val2.4 |
----------------------------------------------------------------------------------
| Val3.1 | Val3.2 | Val3.3 | 3 | Val3.4 |
----------------------------------------------------------------------------------
| Val4.1 | Val4.2 | Val4.3 | 4 | Val4.4 |
Here is an example of the result set that I get when I use the linq to entities:
| EntityKey1 | EntityKey2 | EntityKey3 | NonEntityKey1 | NonEntityKey2 |
----------------------------------------------------------------------------------
| Val1.1 | Val1.2 | Val1.3 | 1 | Val1.4 |
----------------------------------------------------------------------------------
| Val2.1 | Val2.2 | Val2.3 | 1 | Val1.4 |
----------------------------------------------------------------------------------
| Val3.1 | Val3.2 | Val3.3 | 1 | Val1.4 |
----------------------------------------------------------------------------------
| Val4.1 | Val4.2 | Val4.3 | 1 | Val1.4 |
Why am I seeing the results that I'm seeing and how do I fix it to return the correct data without making the non entity key fields entity keys? (They can't be keys cause they are nullable)
EDIT:
I should also point out that when I do the following query I don't see the same issues...but I really would like things to work as I've stated before.
using (Entities context = new Entities())
{
string formattedStr = Decimal.Parse(str).ToString();
var objs = (from obj in context.EntityObjs
where obj.Number == formattedStr
orderby obj.EntityKey3 , obj.NonEntityKey2, obj.NonEntityKey1
select new
{
EntityKey1 = obj.EntityKey1,
EntityKey2 = obj.EntityKey2,
EntityKey3 = obj.EntityKey3,
NonEntityKey1 = obj.NonEntityKey1,
NonEntityKey2 = obj.NonEntityKey2
});
// Process results...
}
I guess the problem could be because you might not have a good primary key in your entity object. Take a look at the solution given here.. This might solve your problem if this is your issue.
How to compare everytime, the current record with the previous record in the same table using MySQL C# in MVC3.0.
This is my table
Historytable:
id | projid| task | name | description | date | type
----|-------| ----- | -------------- |------------ | -------| ---------
1 | 1 | sys21 | validation | validating user | 1-5-12 | created
2 | 1 | sys21 | bug tracking | background bug | 23-7-12 | updated
| | | | tracking | |
3 | 1 | sys21 | bug tracking | bug reporting | 30-8-12 | updated
4 | 1 | sys21 | bugs | bug reporting | 12-9-12 | updated
----------------------------------------------------------------------------------
now i want the result such that compare the record of type updated with the previous record in order to show the previous record as the previous history and record obtained by comparing with the previous record and display only the updated fields as the current history.
now depending upon the projid retrieve the history.
and my view look like the below:
previous history current history
---------------- ---------------
type: created
name: validation
description: validating user
--------------------------------------------------------------
type: created updated
name validation bug tracking
description: validating user background bug tracking
--------------------------------------------------------------------
type: updated updated
name: bug tracking bug report
description: background bug tracking bug reporting
----------------------------------------------------------------
type: updated updated
name: bug tracking -
Description: background bug tracking bug reporting
------------------------------------------------------------------------
type: updated updated
name: bug tracking bugs
Description: bug reporting -
I am expecting the above output, any one plz help me out from the situation,
any king of sugesions will be accepted...
Thankyou,
I am not sure I understood you correctly but you could approach this with the following logic:
Get the rows that represent the history of an item and order by date descending
Get the first row from above as the last change
Get the second row from 1. as the previous to last change
Compare the data
Here's a potential approach for this (using Linq):
var history = db.History.Where(item => item.ProjId == 1)
.OrderByDescending(item => item.Date);
var lastChange = history.First();
var previousChange = history.Skip(1).First();
Now you need to send the above rows to your comparison method. If you want to highlight the changes, you can iterate through properties of the rows and compare values for same properties like this:
private IEnumerable<Tuple<string, object, object>> GetChangesBetweenRows(History row1, History row2)
{
var result = new List<Tuple<string, object, object>>();
var properties = lastChange.GetType().GetProperties(); // both rows are of the same type
foreach(var propInfo in properties)
{
var obj1 = propInfo.GetValue(lastChange, null);
var obj2 = propInfo.GetValue(previousChange, null);
if(obj1 != obj2)
result.Add(Tuple.Create(propInfo.Name, obj1, obj2));
}
return result;
}
EDIT
Given the method above, you can iterate through a collection of history rows and get differences between any of two rows in the collection:
static void Main(string[] args)
{
var history = db.History.Where(item => item.ProjId == 1)
.OrderBy(item => item.Date)
.ToArray();
for(int i=1; i<history.Length; i++)
{
var diff = GetChangesBetweenRows(history[i-1], history[i]);
DisplayDifferences(diff);
}
}
static void DisplayDifferences(IEnumerable<Tuple<string, object, object>> diff)
{
foreach(var tuple in diff)
{
Console.WriteLine("Property: {0}. Object1: {1}, Object2: {2}",tuple.Item1, tuple.Item2, tuple.Item3);
}
}
I have two tables that are linked n-n. And I have a method that takes one object and saves.
public int Save(Table1 element)
{
using (var database = new Entities())
{
if (element.ID == 0)
{
database.Table1.AddObject(element);
}
else
{
database.Attach(element); //
database.ObjectStateManager.GetObjectStateEntry(element).SetModified();
database.Refresh(RefreshMode.ClientWins, element);
}
return database.SaveChanges();
}
}
When I don't try to modify obj1.Table2 it attaches and saves successfully. But if I try to modify this EntityCollection
element.Table2.Add(tb2);
And save, I get the following error:
An object with a temporary EntityKey value cannot be attached to an object context.
at Line: database.Attach(element);
How can I fix it?
Database:
Table 1 Table 2
ID | Name ID | Name
--------- -------------------
1 | One 1 | Related to One
2 | Two 2 | Related to One
3 | Three
Table 3
Tb1 | Tb2
---------
// 1 | 1
// 1 | 2
Creating Table1 object:
var element = GetTable1Obj(1);
element.Table2.Add(GetTable2Obj(1)); // GetTable2Obj uses a separated context
element.Table2.Add(GetTable2Obj(2)); // like Save method to return the object
provider.Save(element); // Method above
If Your Entity frame work model is set to something like this You should be able to modify t1 or t2 without having issues. while still keeping
From the looks of table 3 in your example you don't have a key for the entries.
Which will cause issues when modifying the Entity Object. What is your DB Fk set at.