CopyToDataTable in LINQ - linq

With the reference of this i add a methods in WebForm1.aspx.cs
Reference link
but when i add and build my code then there is error
Extension method must be defined in a top level static class; CustomLINQtoDataSetMethods is a nested class
Extension method must be defined in a top level static class; CustomLINQtoDataSetMethods is a nested class
I do this because i have web method
[WebMethod]
public static DataTable search_data(DateTime fromdate, DateTime todate, string regiondrop)
{
try
{
T1 ts = new T1();
var dq = (from vv in ts.tblVe
join rv in ts.tblReg on vv.ID equals rv.ID
join re in ts.tblRegi on rv.RID equals re.RID
where
re.Region == regiondrop
&& re.StartDate <= fromdate
&& re.EndDate >= todate
orderby
vv.ID,
rv.OwnerName
select new
{
ID = vv.ID,
ownername = rv.OwnerName,
RegNo = rv.RegNo,
Speed = rv.Speed,
});
var dt = dq.cop();
}
catch (Exception)
{
throw new Exception();
}
}
when i add this line var dt = dq.cop(); with the reference and answer of this question reference 2 then CopyToDataTable is not in intellisence list
In dq the data is
[0] = { ID = 1, OName = "Khn", RegNo = "AJ-24",Speed = "124" }
[1] = { ID = 2, OName = "hah", RegNo = "AL-91",Speed = "95" }

It tells exactly what the problem is. You have to define extention methods in a public not-nested class. As mentioned on MSDN:
public static class CustomLINQtoDataSetMethods
{
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source)
{
return new ObjectShredder<T>().Shred(source, null, null);
}
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source,
DataTable table, LoadOption? options)
{
return new ObjectShredder<T>().Shred(source, table, options);
}
}
And you've most likely put the CustomLINQtoDataSetMethods inside other class. Make sure it's outside of any other classes and the issue should be fixed.

Related

Oracle sequence EF Core 6.0?

I need to get a NEXTVAL from a SEQUENCE in an Oracle database. The modelbuilder does have a
builder.HasSequence("TABLE_SEQ");
But I have no clue on how to use that. The only way I can think of is scalar executing a raw SQL to retrieve the next value. Is that the way to go or are there better ways to do this?
I've found several posts that say I should use context.Database.SqlQuery() but in my solution that is missing. Do I need to add a library to get this functionality for EF 6.0?
Examples I found:
Example 1:
public int GetNewCertificateTradeRequestIdentity()
{
using var command = _context.Database.GetDbConnection().CreateCommand();
command.CommandText = "SELECT ts.seq_certificate_trade_request.NEXTVAL FROM DUAL";
_context.Database.OpenConnection();
using var reader = command.ExecuteReader();
reader.Read();
return reader.GetInt32(0);
}
Example 2:
users = await context.Database.SqlQuery<User>("Select * from User", new object[] { }).ToListAsync();
Both the _context.Database.GetDbConnection() context.Database.SqlQuery<x> are missing. Where can I find them?
Ok, in EF6 you have the context.Database.GetDbConnection().CreateCommand(). With that command you can execute a query on the database and receive the result. I've also found a solution for getting the tablename from the EF6 Metadata and added an extension method to handle that. Now I can do the the following:
private Tijdverantwoording Create(decimal? mdwid, decimal? deelprjid, Datum? date)
{
if (mdwid == null || deelprjid == null || date == null) throw new ArgumentNullException();
Weekstaatstatus weekstaatStatus = _WeekstaatStatusService.GetOrCreate(mdwid.Value, date.Jaarweekcode, WeekStaatStatussen.InBewerking, DateTime.Now);
var tijdverantwoording = new Tijdverantwoording
{
Tijdverantwoordingid = GetId<Tijdverantwoording>(), // <= Generate id
Mdwid = mdwid.Value,
Deelprjid = deelprjid.Value,
Datum = date.DagDatum,
Syncstatus = (decimal)SyncStatuses.InBewerking,
Syncdate = DateTime.Now.Date,
Weekstaatstatusid = weekstaatStatus.Weekstaatstatusid
};
_modelContext.Tijdverantwoordingen.Add(tijdverantwoording);
return tijdverantwoording;
}
The base class used for a service.
using Microsoft.EntityFrameworkCore;
using MyProjects.Core.Extensions;
using MyProjects.Core.Model;
namespace MyProjects.Core.Services
{
public class ServiceBase
{
private ModelContext? _modelContext;
public ServiceBase(ModelContext modelContext)
{
_modelContext = modelContext;
}
public decimal GetId<T>()
where T : class
{
var command = _modelContext.Database.GetDbConnection().CreateCommand();
var tableName = _modelContext.TableName(typeof(T));
command.CommandType = System.Data.CommandType.Text;
command.CommandText = $"SELECT {tableName}_SEQ.NEXTVAL FROM DUAL";
_modelContext.Database.OpenConnection();
try
{
var result = (decimal?)command.ExecuteScalar();
return result.Value;
}
finally
{
_modelContext.Database.CloseConnection();
}
}
}
}
And the extension method
using Microsoft.EntityFrameworkCore;
namespace MyProjects.Core.Extensions
{
public static class DatabaseExtensions
{
public static string? TableName(this DbContext context, Type type)
{
var entityType = context.Model.FindEntityType(type);
return entityType?.GetTableName() ?? throw new NullReferenceException($"Can't find name for type {type.Name}");
}
}
}

How to select multiple class properties in LINQ Expression?

If I have a class like this
`
class Person
{
public string First;
public string Last;
public bool IsMarried;
public int Age;
}`
Then how can I write a LINQ Expression where I could select properties of a Person. I want to do something like this (user can enter 1..n properties)
SelectData<Person>(x=>x.First, x.Last,x.Age);
What would be the input expression of my SelectData function ?
SelectData(Expression<Func<TEntity, List<string>>> selector); ?
EDIT
In my SelectData function I want to extract property names and then generate SELECT clause of my SQL Query dynamically.
SOLUTION
Ok, so what I have done is to have my SelectData as
public IEnumerable<TEntity> SelectData(Expression<Func<TEntity, object>> expression)
{
NewExpression body = (NewExpression)expression.Body;
List<string> columns = new List<string>();
foreach(var arg in body.Arguments)
{
var exp = (MemberExpression)arg;
columns.Add(exp.Member.Name);
}
//build query
And to use it I call it like this
ccc<Person>().SelectData(x => new { x.First, x.Last, x.Age });
Hopefully it would help someone who is looking :)
Thanks,
IY
I think it would be better to use delegates instead of Reflection. Apart from the fact that delegates will be faster, the compiler will complain if you try to fetch property values that do not exist. With reflection you won't find errors until run time.
Luckily there is already something like that. it is implemented as an extension function of IEnumerable, and it is called Select (irony intended)
I think you want something like this:
I have a sequence of Persons, and I want you to create a Linq
statement that returns per Person a new object that contains the
properties First and Last.
Or:
I have a sequence of Persns and I want you to create a Linq statement
that returns per Person a new object that contains Age, IsMarried,
whether it is an adult and to make it difficult: one Property called
Name which is a combination of First and Last
The function SelectData would be something like this:
IEnumerable<TResult> SelectData<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
return source.Select(selector);
}
Usage:
problem 1: return per Person a new object that contains the
properties First and Last.
var result = Persons.SelectData(person => new
{
First = person.First,
Last = person.Last,
});
problem 2: return per Person a new object that contains Age, IsMarried, whether he is an adult and one Property called Name which is a combination
of First and Last
var result = Persons.SelectData(person => new
{
Age = person.Name,
IsMarried = person.IsMarried,
IsAdult = person.Age > 21,
Name = new
{
First = person.First,
Last = person.Last,
},
});
Well let's face it, your SelectData is nothing more than Enumerable.Select
You could of course create a function where you'd let the caller provide a list of properties he wants, but (1) that would limit his possibilities to design the end result and (2) it would be way more typing for him to call the function.
Instead of:
.Select(p => new
{
P1 = p.Property1,
P2 = p.Property2,
}
he would have to type something like
.SelectData(new List<Func<TSource, TResult>()
{
p => p.Property1, // first element of the property list
p -> p.Property2, // second element of the property list
}
You won't be able to name the returned properties, you won't be able to combine several properties into one:
.Select(p => p.First + p.Last)
And what would you gain by it?
Highly discouraged requirement!
You could achive similar result using Reflection and Extension Method
Model:
namespace ConsoleApplication2
{
class Person
{
public string First { get; set; }
public string Last { get; set; }
public bool IsMarried { get; set; }
public int Age { get; set; }
}
}
Service:
using System.Collections.Generic;
using System.Linq;
namespace Test
{
public static class Service
{
public static IQueryable<IQueryable<KeyValuePair<string, object>>> SelectData<T>(this IQueryable<T> queryable, string[] properties)
{
var queryResult = new List<IQueryable<KeyValuePair<string, object>>>();
foreach (T entity in queryable)
{
var entityProperties = new List<KeyValuePair<string, object>>();
foreach (string property in properties)
{
var value = typeof(T).GetProperty(property).GetValue(entity);
var entityProperty = new KeyValuePair<string, object>(property, value);
entityProperties.Add(entityProperty);
}
queryResult.Add(entityProperties.AsQueryable());
}
return queryResult.AsQueryable();
}
}
}
Usage:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var list = new List<Person>()
{
new Person()
{
Age = 18,
First = "test1",
IsMarried = false,
Last = "test2"
},
new Person()
{
Age = 40,
First = "test3",
IsMarried = true,
Last = "test4"
}
};
var queryableList = list.AsQueryable();
string[] properties = { "Age", "Last" };
var result = queryableList.SelectData(properties);
foreach (var element in result)
{
foreach (var property in element)
{
Console.WriteLine($"{property.Key}: {property.Value}");
}
}
Console.ReadKey();
}
}
}
Result:
Age: 18
Last: test2
Age: 40
Last: test4

Use common linq expression to avoid duplicate of entity to poco

How may I avoid to duplicate the code I use for mapping a database entity to a poco object?
Given this code:
private IQueryable<DummyExtended> Find()
{
return (from dt in Entities.dummy_table
select new DummyExtended
{
Description = dt.table_1.table_2.description,
Dummy = new Dummy
{
Name = d.name,
Notes = d.notes,
HelpText = d.help_text
}
}).AsQueryable();
}
Can I create a common linq expression to be re-used for both methods?
private IQueryable<DummyExtended> Find()
{
return (from dt in Entities.dummy_table
select new DummyExtended
{
Description = dt.table_1.table_2.description,
Dummy = ...???
}).AsQueryable();
}
private IQueryable<DummyAlsoExtended> FindAnother()
{
return (from dt in Entities.dummy_table
select new DummyAlsoExtended
{
InnerHtml = dt.table_html.description,
Dummy = ....??
}).AsQueryable();
}
Example:
public static Expression<Func<dummy_table, Dummy>> EntityToPoco()
{
return d => new Dummy
{
Name = d.name,
Notes = d.notes,
HelpText = d.help_text
};
}
I can't quite get it right
....
Dummy = ExtensionClass.EntityToPoco()
So you have a dummy_table which is a Enumerable or Queryable sequence of objects. Let's assume that the sequence contains objects of class DummyTableElement.
You showed, that if you have a DummyTableElement you know how to convert it into a Dummy object. You want to reuse this function to create other objects like DummyExtended and DummyAlsoExtended. If you want to do this LINQ-alike, it is best to create extension functions for it:
static class DummyTableElementExtensions
{
public static Dummy ToDummy(this TableElement tableElement)
{
return new Dummy()
{
Name = tableElement.name,
Notes = tableElement.notes,
HelpText = tableElement.help_text
};
}
}
Once you have this, you can create similar functions to convert TableElements into DummyExtended and DummyAlsoExtended. They will be one-liners.
In the same extension class:
public static DummyExtended ToDummyExtended(this TableElement tableElement)
{
return new DummyExtended()
{
Description = tableElement.table_1.table_2.description,
Dummy = tableElement.ToDummy(),
};
}
public static DummyAlsoExtended ToDummyAlsoExtended(this TableElement tableElement)
{
return new DummyAlsoExtended
{
InnerHtml = tableElement.table_html.description,
Dummy = tableElement.ToDummy(),
};
}
And once you've got these, you can create extension functions to convert any IQueryable of TableElements:
public static IQueryable<DummyExtended> ToDummyExtended(
this IQueryable<TableElement> tableElements)
{
return tableElements
.Select(tableElement => tableelement.ToDummyExtended();
}
And a similar one-line function for DummyAlsoExtended.
Your Find function and FindAnother function will also be one-liners:
private IQueryable<DummyExtended> Find()
{
return dummy_table.ToDummyExtended();
}
private IQueryable<DummyAlsoExtended> FindAnother()
{
return dummy_table.ToDummyAlsoExtended();
}
I'm not sure why you wanted to use an expression in this. It doesn't seem that DummyExtended and DummyAlsoExtended are really similar, except that they both have a property Dummy.
One reason to parameterize the destination of your find function could be because you want to create anonymous classes in your Find function.
Again, once you've created ToDummy this will be a one-liner:
public static IQueryable<TResult> Find<TSource, TResult>(
this IQueryable<TSource> source,
Expression<Func<TSource, TResult>> resultSelector)
{
return source.Select(sourceElement => resultSelector(sourceElement);
}
Usage would be:
var X = dummy_Table.find(tableElement => new
{
foo = tableElement.CalculateFoo(),
bar = tableElement.CalculateBar(),
Dummy = tableElement.ToDummy(),
});

List Distinct is not working in LINQ instead of GroupBy

Thanks in advance. I can get required output when using var but i want to get required output by using Distinct in List<>.
InventoryDetails.cs
public class InventoryDetails
{
public int? PersonalInventoryGroupId { get; set; }
public int? PersonalInventoryBinId { get; set; }
}
InventoryController.cs
[HttpGet("GetInventory")]
public IActionResult GetInventory(int id)
{
//Below code will return distinct record
var inventory = (from i in _context.TempTbl
where i.TempId == id
select new
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).ToList().Distinct().ToList();
//Below code is not doing distinct
List<InventoryDetails> inventory = (from i in _context.TempTbl
where i.TempId == id
select new InventoryDetails
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).ToList().Distinct().ToList();
}
If i use var as return type, then i am able to get distinct records. Could some one assist it.
Please try like this it may help.
IList<InventoryDetails> inventory = _context.InventoryDetails.Where(x=>x.TempId == id).GroupBy(p => new {p.PersonalInventoryGroupId, p.PersonalInventoryBinId } )
.Select(g => g.First())
.ToList();
You need to override Equals and GetHashCode.
First, let's see the AnonymousType vs InventoryDetails
var AnonymousTypeObj1 = new { PersonalInventoryGroupId = 1, PersonalInventoryBinId = 1 };
var AnonymousTypeObj2 = new { PersonalInventoryGroupId = 1, PersonalInventoryBinId = 1 };
Console.WriteLine(AnonymousTypeObj1.Equals(AnonymousTypeObj2)); // True
var InventoryDetailsObj1 = new InventoryDetails { PersonalInventoryBinId = 1, PersonalInventoryGroupId = 1 };
var InvertoryDetailsObj2 = new InventoryDetails { PersonalInventoryBinId = 1, PersonalInventoryGroupId = 1 };
Console.WriteLine(InventoryDetailsObj1.Equals(InvertoryDetailsObj2)); // False
You can see the Equals behave differently which make Distinct behave differently. The problem is not var you mentioned in your question but AnonoymizeType
To make Distinct works as you expect, you need to override Equals and GetHashCode
public class InventoryDetails
{
public int? PersonalInventoryGroupId { get; set; }
public int? PersonalInventoryBinId { get; set; }
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj is InventoryDetails)
{
if (PersonalInventoryGroupId == (obj as InventoryDetails).PersonalInventoryGroupId
&& PersonalInventoryBinId == (obj as InventoryDetails).PersonalInventoryBinId)
return true;
}
return false;
}
public override int GetHashCode()
{
int hash = 17;
hash = hash * 23 + PersonalInventoryBinId.GetHashCode();
hash = hash * 23 + PersonalInventoryGroupId.GetHashCode();
return hash;
}
}
Another approach would be
List<InventoryDetails> inventory = (from i in TempTbl
where i.TempId == id
select new InventoryDetails
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).AsQueryable().ToList().Distinct(new customComparer()).ToList();
public class customComparer:IEqualityComparer<InventoryDetails>
{
public bool Equals(InventoryDetails x, InventoryDetails y)
{
if (x.TempId == y.TempId && x.PersonalInventoryBinId == y.PersonalInventoryBinId
&& x.PersonalInventoryGroupId == y.PersonalInventoryGroupId)
{
return true;
}
return false;
}
public int GetHashCode(InventoryDetails obj)
{
return string.Concat(obj.PersonalInventoryBinId.ToString(),
obj.PersonalInventoryGroupId.ToString(),
obj.TempId.ToString()).GetHashCode();
}
}
As said in a comment by Ivan, you make your life difficult by calling ToList before Distinct. This prevents the SQL provider from incorporating the Distinct call into the generated SQL statement. But that leaves the question: what causes the difference?
The first query generates anonymous type instances. As per the C# specification, by default anonymous types (in C#) are equal when their properties and property values are equal (structural equality). Conversely, by default, reference types (like InventoryDetails) are equal when their reference (say memory address) is equal (reference equality or identity). They can be made equal by overriding their Equals and GetHashcode methods, as some people suggested to do.
But that's not necessary if you remove the first ToList():
var inventory = (from i in _context.TempTbl
where i.TempId == id
select new InventoryDetails
{
PersonalInventoryBinId = i.PersonalInventoryBinId,
PersonalInventoryGroupId = i.PersonalInventoryGroupId,
}).Distinct().ToList();
Now the whole statement until ToList() is an IQueryable that can be translated into SQL. The SQL is executed and the database returns a distinct result set of raw records from which EF materializes InventoryDetails objects. The C# runtime code was even never aware of duplicates!

Help with linq2sql generic lambda expression

In my Database almost every table has its own translations table. I.e. Sports has SportsTranslations table with columns: SportId, LanguageId, Name. At the moment I'm taking translations like:
int[] defaultLanguages = { 1, 3 };
var query = from s in dc.Sports
select new
{
sportName = s.SportsTranslations.Where(st => defaultLanguages.Contains(st.LanguageID)).First()
};
I wonder is it possible to implement some kind of generic method, so I could refactor code like here:
var query = from s in dc.Sports
select new
{
sportName = s.SportsTranslations.Translate()
};
Solved. Here is the static method I written:
public static class Extras
{
public static T Translate<T>(this IEnumerable<T> table) where T : class
{
try
{
return table.Where(
t => defaultLanguages.Contains(
(int)t.GetType().GetProperty("LanguageID").GetValue(t, null)
)
).First();
}
catch (Exception)
{
throw new ApplicationException(string.Format("No translation found in table {0}", typeof(T).Name));
}
}
}

Resources