Random Row from SQL Server DB using DLINQ - sql-server

I need to retrieve random rows from SQL Server database. I am looking for a way to achieve this using LINQ query. Is it possible?
SQL Query: SELECT [Id] FROM [MyTable] ORDER BY NEWID()
What is the equivalent LINQ query for the above SQL?
Thanks in advance.

Make a partial for your data context class and put in the following method:
partial class MyDataContext {
[Function(Name = "NEWID", IsComposable = true)]
public Guid Random()
{
return Guid.NewGuid();
}
}
Now you can compose this into your query and it'll get translated into calls to the sql newid() function like so:
from x in dc.MyEntities orderby dc.Random() select x.Id

Related

SQL Server 2016 SSIS get cursor from stored procedure

I am using SQL Server 2016.
I have a stored procedure GET_RECORDS that takes input parameters for filter and outputs a CURSOR parameter
I want to get this cursor in my SSIS package
I had created data flow task, OleDb source and variables for parameter values. Then mapped parameters
Params mapping screen
but when I wanted to save the component - I got an error
error screen
I tried to add clause WITH RESULT SETS with some dummy columns, but my procedure doesn't return any result set
What am I doing wrong?
Any advices will be helpful.
Thank you.
With regards, Yuriy.
The source component is trying to determine what columns and types will be returned. Because you are using dynamic SQL the metadata can change each time you run it.
With result sets allows you to define the data being returned but should only be used if you are guaranteed to have those results every time you execute.
EDIT:
I create a connection and run the command so that it populates a data table. Then I put the column headers into a string array. There are plenty of examples out there.
Then I use the following function to create a destination table. Finally I create a datareader and pass that to the .Net SqlBulkCopy. Hope this helps.
private void CreateTable(string TableName, string[] Fields)
{
if (TableExists(TableName) && Overwrite)
{
SqlCommand = new SqlCommand($"Drop Table [{TableName}]", SqlConnection);
SqlCommand.ExecuteNonQuery();
}
string Sql = $"Create Table [{TableName}] (";
int ColumnNumber = 1;
foreach (string Field in Fields)
{
string FieldValue = Field;
if (! HasHeaders)
{
FieldValue = "Column" + ColumnNumber;
ColumnNumber++;
}
Sql += $"[{FieldValue}] Varchar(8000),";
}
Sql = Sql + "ImportFileID Int, ID Int Identity(1,1) Not Null, Constraint [PK_" + TableName + "] Primary Key Clustered ([ID] Asc))";
SqlCommand = new SqlCommand(Sql, SqlConnection);
SqlCommand.ExecuteNonQuery();
}
Use ado.net source instead of oledb source, define a simple select and get the columns you wish to return. Now you can define expresión in the dataflow properties.
Search ado.net source dynamic sql
:)
try to return the records and use foreach in ETL instead of cursor
https://www.simple-talk.com/sql/ssis/implementing-foreach-looping-logic-in-ssis/
I think you can do it from a simple way, but I don't know what you are you doing, exactly...

NHibernate ORDER BY CURRENT_TIMESTAMP conflicts with DISTINCT

Could anybody please explain why NHibernate on MsSql2012Dialect generates query that can not be processed by server? It builds query this way when there is no sorting specified explicitly.
...
ORDER BY CURRENT_TIMESTAMP
OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY
This is unresolved bug registered in jira, based on the suggestions, this is my work around:
public class MyMsSql2012Dialect : MsSql2012Dialect
{
public override SqlString GetLimitString(SqlString querySqlString, SqlString offset, SqlString limit)
{
var result = base.GetLimitString(querySqlString, offset, limit);
return result.Replace("ORDER BY CURRENT_TIMESTAMP", "ORDER BY 1");
}
}
As you said in the question, following query is generated if no ORDER BY is explicitly specified:
SELECT
distinct this_.ColumnName as y0_
FROM
[DB].[dbo].Table this_
ORDER BY
CURRENT_TIMESTAMP OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY;
Error is:
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
Error only occur if BOTH Projections.Distinct and Take(1) is provided and SQL Server version is above 2012 (Dialect is MsSql2012Dialect or above).
The better solution is to provide the ORDER BY column to NHibernate explicitly and include that column in SELECT list.
Session.QueryOver<Entity>()
.Select(
Projections.Distinct(Projections.Property<Entity>(x => x.ColumnName))
)
.Where(....)
.OrderBy(Projections.Property<Entity>(x => x.ColumnName)).Asc()
.Take(1);

Accessing new field value generated in SQL via dbContext

I'm using dbContext and I am running a SQL query that is rather complex (just showing a simple example below), so to avoid having to run the query twice to get a count, I am using COUNT AS to return the total number of records as per other advice on this site.
But, I haven't been able to figure out how to access the resulting property:
using (var db = new DMSContext())
{
string queryString = "select *, COUNT(1) OVER() AS TotalRecords FROM DMSMetas";
var Metas = db.DMSMetas.SqlQuery(queryString).ToList();
for (int i = 0; i <= Metas.Count - 1; i++)
{
var Item = Metas[i];
if (i == 0)
{
//Want to do this, but TotalRecords not part of the DMSMeta class. How to access the created column?
Console.WriteLine("Total records found: " + Item.TotalRecords);
}
}
}
In the sample above, the SQL query generates the extra field TotalRecords. When I run the query in Management Studio, the results are as expected. But how do I access the TotalRecords field through dbContext?
I also tried including the TotalRecords field as part of the DMSMeta class, but then the SQL query fails with the error that the TotalRecords field is specified twice. I tried creating a partial class for DMSMeta containing the TotalRecords field, but then the value remains the default value and is not updated during the query.
I also tried the following:
db.Entry(Item).Property("TotalRecords").CurrentValue
But that generated an error too. Any help would be much appreciated - I am sure I am missing something obvious! All I want is to figure out a way to access the total number of records returned by the query
you have to create a new class (not an entity class but a pure DAO class) DMSMetaWithCount (self explanatory ?) and then
context.Database.SqlQuery<DMSMetaWithCount>("select *, COUNT(1) OVER() AS TotalRecords FROM DMSMetas");
please note that
imho, select * is ALWAYS a bad practice.
you will have no tracking on the not entity new class

What is the correct syntax for an Ormlite GROUP BY query?

Using ServiceStack.OrmLite with SQL Server I am trying to achieve a GROUP BY query over a mapped entity on to a DTO object but I can't seem to get the OrmLite syntax right.
The mapped entity looks like this:
public class MacRequestLetter
{
[PrimaryKey]
public Guid BatchId { get; set; }
[PrimaryKey]
public Guid Id { get; set; }
public DateTime LetterDate { get; set; }
/*
... elided - more properties relevant to this entity ...
*/
}
If I was writing the SQL manually this is what I'd write:
SELECT
BatchId
,COUNT(*) AS LetterCount
,MAX(LetterDate) AS LetterDate
FROM
dbo.MacRequestLetter
GROUP BY
BatchId
ORDER BY
LetterDate DESC
Here is the Ormlite query that I've attempted to achieve this with:
return db.Select<MacLetterBatch>(
db.From<MacRequestLetter>()
.Select(letter => new {
BatchId = letter.BatchId,
LetterCount = Sql.Count("*"),
LetterDate = Sql.Max(letter.LetterDate)
})
.GroupBy(letter => letter.BatchId)
.OrderByDescending(letter => Sql.Max(letter.LetterDate))
);
where MacLetterBatch is a DTO with properties matching the select part of the query.
However when I run this I get a sql error with message Column 'MacRequestLetter.LetterDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
The SQL that is sent to the server is:
SELECT "MacRequestLetter"."BatchId", "MacRequestLetter"."LetterDate"
FROM "MacRequestLetter"
GROUP BY "BatchId"
ORDER BY Max("LetterDate") DESC
which is clearly wrong in the way pointed out by the exception.
Can anyone tell me what is wrong with my OrmLite code? What code would achieve my goal?

Importing SQL Server's CONTAINS() as a model defined function

I am trying to import SQL Server's CONTAINS() function in my Entity Framework model so that I can use it in my LINQ queries.
I have added this to my EDM:
<Function Name="FullTextSearch" ReturnType="Edm.Boolean">
<Parameter Name="Filter" Type="Edm.String" />
<DefiningExpression>
CONTAINS(*, Filter)
</DefiningExpression>
</Function>
Add created my method stub:
[EdmFunction("MyModelNamespace", "FullTextSearch")]
public static bool FullTextSearch(string filter)
{
throw new NotSupportedException("This function is only for L2E query.");
}
I try to call the function like this:
from product in Products
where MyModel.FullTextSearch("FORMSOF(INFLECTIONAL, robe)")
select product
The following exception is raised:
The query syntax is not valid. Near term '*'
I realize that the function I defined is not directly linked to the entity set being queried so that could also be a problem.
Is there any way to pull this off?
The function you have defined above uses Entity SQL, not Transact SQL, so I think the first step is to figure out whether CONTAINS(*,'text') can be expressed in Entity SQL.
Entity SQL doesn't support the * operator as described here: http://msdn.microsoft.com/en-us/library/bb738573.aspx and if I try
entities.CreateQuery<TABLE_NAME>("select value t from TABLE_NAME as t where CONTAINS(*, 'text')");
I get the same error you got above. If I try to explicitly pass the column it works:
entities.CreateQuery<TABLE_NAME>("select value t from TABLE_NAME as t where CONTAINS(t.COLUMN_NAME, 'text')");
But when I look at the SQL it translated it to a LIKE expression.
ADO.NET:Execute Reader "SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[TABLE_NAME] AS [Extent1]
WHERE (CASE WHEN ([Extent1].[COLUMN_NAME] LIKE '%text%') THEN cast(1 as bit) WHEN ( NOT ([Extent1].[COLUMN_NAME] LIKE '%text%')) THEN cast(0 as bit) END) = 1
) AS [GroupBy1]"
If you cannot express the query using Entity SQL you'll have to use a Stored Procedure or other mechanism to use Transact SQL directly.
This is way beyond me but could you try
from product in Products where MyModel.FullTextSearch(product, "FORMSOF(INFLECTIONAL, robe)") select product
My reasoning is that in SQL Server it is expecting two parameters.
I inserted a little function into my code, in a class which inherits from the Context class, which points to my SQL function supporting Full Text searching, my solution is a little more closed ended to yours (not allowing the specification of the type of text search), it returns an IEnumerable, essentially a list of primary keys matching the searching criteria, something like this;
public class myContext : DataContext
{
protected class series_identity
{
public int seriesID;
series_identity() { }
};
[Function(Name = "dbo.fnSeriesFreeTextSearchInflectional", IsComposable = true)]
protected IQueryable<series_identity> SynopsisSearch([Parameter(DbType = "NVarChar")] string value)
{
return this.CreateMethodCallQuery<series_identity>(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), value);
}
public IEnumerable<int> Search(string value)
{
var a = from t1 in SynopsisSearch(value)
select t1.seriesID;
return a;
}
};
usage is something like;
myContext context = new myContext();
IEnumerable<int> series_identities = (from t1 in context.Search("some term")
select t1).Distinct();

Resources