I'm using LINQPad and I would like to know schema details of a table.
I know that I do it using SQL:
SELECT column_name,*
FROM information_schema.columns
WHERE table_name = '{table_name}'
ORDER BY ordinal_position
How can I do this using LINQ?
LINQ to SQL contexts have a Mapping property that you can use for this sort of thing. A query like the one you provided might look something like this:
from t in context.Mapping.GetTables()
where t.TableName == "[table_name]"
from c in t.RowType.DataMembers
orderby c.Ordinal
select new {columnName = c.Name, columnInfo = c}
See this answer for more details.
MetaTable t = MyDataContext.Mapping.GetTables().Where(
i => i.TableName == "TABLENAME").SingleOrDefault();
PropertyInfo[] fields = t.RowType.InheritanceRoot.GetType().GetProperties();
'fields' will contain the names and types of the columns.
In LINQ to SQL, you could try to bring in these views into the model. If that does not work, you could create a stored procedure that retrieves the info, then LINQ to SQL maps the stored procedure and you execute it as a function.
Related
If I have a summary class of some objects I need ( for example its primary key, etc..) is there a way to use a list of that class object when I am writing a joining to other tables? so all the things in my LINQ query are real table like this.Context.MyTable but one of them be my List<MyClass> ?
or is there any LINQ related Nuget project that makes this possible?
The EF LINQ queries aren't actually code that is run in C#, they are converted to SQL and run on the database server; so you can't join them with an in-memory array (or List<T>). What you can do, is use Contains like so:
public IEnumerable<Table1> GetThingsFromDatabse(DataContext db, IList<MyObject> objects)
{
var ids = objects.Select(x => x.Id).ToList();
var results = Enumerable.ToList(
from x in db.Table1s
where ids.Contains(x.Id)
select x
);
return results;
}
This gets translated into SQL that looks like this:
SELECT *
FROM [Table1] x
WHERE x.Id IN (#Id1, #Id2, ...)
I have a stored procedure which returns me some dates, as well as an Id which related to a specific row in a table.
Basically, I am getting a list of all scheduled transactions for all accounts within an account portfolio.
The stored procedure returns a row with an Id (for the scheduled transaction), and some dates which I have minded within the proc.
If my query began with:
from p in Context.scheduled_transactions
then this plan would have worked. But I don't want to get the items like that, because in the proc, I am doing a lot of work to create business dates etc. So, instead of bring back the EF model - my proc just brings back the ID. I was HOPING to do something like this:
var trans = (from p in Context.get_scheduled_payments_by_portfolio(portfolioId)
.Include("account")
.Include("cost_centre")
.Include("z_account_transaction_type")
.Include("z_payment_frequency_type")
.Include("transaction_sub_category")
.Include("transaction_sub_category.transaction_category")
.Include("third_party")
select p).ToList();
But, the EF can't use 'Include' as it doesn't know what I am bring back. Although the id is called 'scheduled_transaction_id' in the proc - EF doesn't know that (understandably).
Is there a way I can tell EF that the ID is for a scheduled_transaction_model - and then use the 'Include'?
Maybe I need to just call the proc, which returns me a list of my objects, which has the scheduled_transaction_id, and all the dates I calculated in the proc, and then somehow, use that List<> in another linq query that can join the other tables?
EDIT:
I might be onto something! This doesn't show a syntax error. Just need to create a new Type... Playing with this:
var trans = (from p in Context.get_scheduled_payments_by_portfolio(portfolioId)
join st in Context.scheduled_transaction
.Include("account")
.Include("cost_centre")
.Include("z_account_transaction_type")
.Include("z_payment_frequency_type")
.Include("transaction_sub_category")
.Include("transaction_sub_category.transaction_category")
.Include("third_party")
on p.scheduled_transaction_id equals st.id
select p).ToList();
var ids = Context.get_scheduled_payments_by_portfolio(portfolioId).ToList();
var trans = (from p in Context.scheduled_transaction
.Include("account")
.Include("cost_centre")
.Include("z_account_transaction_type")
.Include("z_payment_frequency_type")
.Include("transaction_sub_category")
.Include("transaction_sub_category.transaction_category")
.Include("third_party")
where ids.Contains(p.id)
select p).ToList();
Try Contains() method which will translated into SQL's IN(,,) statement.
The answer was, join the proc to the table I was using, and then I can use the .Include()
var trans = (from p in Context.get_scheduled_payments_by_portfolio(portfolioId)
join st in Context.scheduled_transaction
.Include("account")
.Include("cost_centre")
.Include("z_account_transaction_type")
.Include("z_payment_frequency_type")
.Include("transaction_sub_category")
.Include("transaction_sub_category.transaction_category")
.Include("third_party")
on p.scheduled_transaction_id equals st.id
select new {st, p}).ToList();
And then with the new type, I can itterate through the list, and build my objects.
I have this query in Sql Server which I need to consume in EntityFramework, So how can I write a EntityFramwork code which will have the same result as this
WITH cte AS
(
SELECT *
FROM StockGroups
WHERE GroupParent ='Stationery'
UNION ALL
SELECT g.*
FROM StockGroups g
JOIN cte
ON g.GroupParent = cte.GroupName
)
SELECT *
FROM cte
I don't know how to convert it in EF, so I tried with join.
from a in db.StockGroups
join b in db.StockGroups on new { GroupParent = a.GroupParent } equals new { GroupParent = b.GroupName }
where
b.GroupName == "Stationery"
select new {
a.GroupName,
a.GroupParent,
Column1 = b.GroupName,
Column2 = b.GroupParent
}
But the result is not same, as recursive as CTE.
EF does not support recursive CTE's. Use a view or a table valued function.
Getting input from the other experts over SO, I have come up with my own way to achieve this.
IEnumerable<StockGroup> sg = dbContext.ExecuteStoreQuery<StockGroup>(
#"WITH q AS
(
SELECT *
FROM LedgerGroups
WHERE GroupParent = 'Customers'
UNION ALL
SELECT m.*
FROM LedgerGroups m
JOIN q
ON m.GroupParent = q.GroupName
)
SELECT *
FROM q
");
You cannot use CTE recursion in Entity Framework.
Use stored procedure and call that stored procedure through EF
I dont think there is support for recursive CTEs in LINQ nor in EF. The solution is to expose the CTE as a view. The article on Recursive or hierarchical queries using EF Code First and Migrations shows how to deploy such a view using EF code first migrations. Recursive or hierarchical queries using EF Code First and Migrations
Original source:
https://stackoverflow.com/a/11929928/3850405
I need to get the distinct row values from a table using LINQ. The query i used is
var results = (from statename in dsobject.dbo_statetable select statename).Distinct();
It is giving all the rows of the table named "dbo_statetable" but i need only the distinct statename. What should be the query to achieve this?
Its sql equivalent is select distinct statename from dbo_statetable
You need to specify the property:
var results = (from x in dsobject.dbo_statetable select x.Statename).Distinct();
// ^^^^^^^^^^
The variable after from does not specify the column. It is like a table alias in SQL. Your LINQ statement is roughly equivalent to this SQL:
SELECT DISTINCT * FROM dbo_statetable AS statename
dsobject.dbo_statetable.Select(s => s.statename).Distinct()
I'm trying to perform a linq to entities query on a table that's inherited using Table per Type.
The problem I'm having is that I can't get at the properties on the Inhertied table only the properties on the Base Table.
var qry = from i in _DB.BaseTable
where i is catalogueModel.InheritedTable
// Field Doesn't Exist
// && i.InheritedTableField == "Value"
select i;
When I try to cast the Inherited Table to it's type...
var qry = from i in _DB.BaseTable
where i is catalogueModel.InheritedTable
&& (i as catalogueModel.InheritedTable).InheritedTableField == "Value"
select i;
...the code compiles but i get a cool error which reads
Only text pointers are allowed in work
tables, never text, ntext, or image
columns. The query processor produced
a query plan that required a text,
ntext, or image column in a work
table.
I suppose my question is How are you supposed to access the properties of the Inherited tables in linq to entities when using Table per Type?
Use .OfType():
var qry = from i in _DB.BaseTable.OfType<InheritedTable>()
select i.InheritedTableField;
You can also use IS
var qry = from i in _DB.BaseTable where i is InheritedTable select i.InheritedTableField;
Here are a few others to help (using Entity SQL)
var q = SELECT VALUE c FROM OFTYPE(yourcontext.yourbaseclass, yourmodel.yoursubclass) AS c
var q = SELECT VALUE c FROM yourcontext.yourbaseclass AS c where c IS NOT OF (yourmodel.yoursubclass)