return linq result via web service - asp.net

I'm trying to use Linq in a webservice that returns a data from a query. As
the data return from Linq to Sql is IEnumerable and it's not possible to
easily get a Dataset.what is the best format to return data?
DataClassesDataContext Dac = new DataClassesDataContext();
Dac.Connection.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionCs"].ConnectionString;
var query = from record in Dac.RetrieveWorkshops(WorkshopCode, Name) select record;

Web-service proxies instantiate collections as arrays, so I've gotten into the habit of defining 'data transfer objects' and returning IEnumerable's of those DTO's. In your case, You could define a WorkshopDTO object which contained only the public properties you wanted to return and have your LINQ query construct them based on each record it reads. Then your client-proxy will see an array of WorkshopDTO's to manipulate.

You can populate your data into an object and return a list of that object in Web Service.
Example:
public class WorkshopEntity
{
string Name { get; set; }
string Location { get; set; }
}
List<WorkshopEntity> workshopList = (from record in Dac.RetrieveWorkshops(WorkshopCode, Name) select new WorkshopEntity { Name=record.name, Location=record.Location }).ToList();

return query.ToArray();
but remember to add [Serializable] Attribiute at top of your WorkshopEntity class.
if your have complex type properties in WorkshopEntity inform me because you should do more.

Related

Stored procedure with Entity Framework get only one column

I want to get specific column of the table but I get this error
The data reader is incompatible with the specified 'NewsDatabaseModel.News'. A member of the type, 'NewsSubject', does not have a corresponding column in the data reader with the same name.
I don't want to use stored procedure via the model I just want to call it.
Here is my code
var NewsList = db.Database.SqlQuery<News_Application.News>("[dbo].[GetAllNews]").ToList();
return View("NewsList");
SQL:
CREATE PROCEDURE GetAllNews
AS
BEGIN
SELECT NewsId, NewsTitle
FROM News
END
Your News_Application.News class must have the same named properties as the returned select from your stored procedure, and all properties must exist in the select sentence.
Since you only want a single column, create a ViewModel class and bind your procedure to it like this:
public class NewsViewModel
{
public int NewsId { get; set;}
public string NewsTitle { get; set; }
}
and bind your procedure
var NewsList = db.Database.SqlQuery<NewsViewModel>("[dbo].[GetAllNews]").ToList();
[EDIT]
For returning an anonymous object, do like this:
var NewsList = db.Database.SqlQuery<NewsViewModel>("[dbo].[GetAllNews]").Select(x => new { x.NewsId, x.NewsTitle }).ToList();
This will return an object that has no class and the properties you need.
Either way, I believe you should reconsider your design. There shouldn't be the need to use a stored procedure for executing such a simple query.
Lets suppose your entity's name is News.
This would suffice:
var NewsList = db.News.Select(x => new { x.NewsId, x.NewsTitle }).ToList();
I'll recommend this website for getting you up to speed with entity framework: http://www.entityframeworktutorial.net/EntityFramework5/entity-framework5-introduction.aspx

How can I issue a SQL Statement against my database and have it create a collection?

I am using EF6 but I don't know if there is any difference between that and earlier versions.
I have the following context:
public IdentityContext()
: base("name=Identity")
{
Database.SetInitializer<IdentityContext>(null);
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
Configuration.ValidateOnSaveEnabled = false;
Configuration.AutoDetectChangesEnabled = true;
Database.Log = logInfo => Debug.WriteLine(logInfo);
}
public DbSet<AspNetRole> AspNetRoles { get; set; }
public DbSet<AspNetUserClaim> AspNetUserClaims { get; set; }
public DbSet<AspNetUserLogin> AspNetUserLogins { get; set; }
public DbSet<AspNetUser> AspNetUsers { get; set; }
What I would like to do is to issue a SQL query against this:
I saw one example (not related to my context) which is:
using (var context = new BloggingContext())
{
var blogs = context.Blogs.SqlQuery("SELECT * FROM dbo.Blogs").ToList();
}
But this does not make any sense to me as I cannot see why there is .Blogs after the context.
For my context above can someone explain how I can issue a simple sql statement to get the Id from the AspNetUser table and place these in a collection.
Note that I am using EF6 but in this case I am not sure that is relevant to the question if I query the context. My real needs are for a complex SQL but first I need some suggestion to get me started. Thanks.
If you're using .SqlQuery, you're kind of bypassing the beauty of using LINQ-style lambda expressions to query your database.
You might need to fiddle with the syntax a bit, but something like this should work for your initial requirement of getting user IDs:
var allMyIds = context.AspNetUserLogins.Select(l => l.Id).ToList();
or, if you prefer...
var allMyIds = (from l in context.AspNetUserLogins
select l.Id).ToList();
However, if you really need to execute SQL directly, you can do it on one of the DBSet classes as in your question (in which case the EF makes a valiant attempt at change tracking), or if it's a general query you just want to execute that returns primitive types and isn't specific to any one table, do it against the Database class using ExecuteSqlCommand:
var allMyIds = context.Database.ExecuteSqlCommand("select id from AspNetUserLogins");
Hope that helps!

Return type for stored procedure returning ints

I have a stored procedure with a simple SELECT statement:
SELECT UserId FROM SomeTable
I find that I need to create a new object in order to wrap it in LINQ.
[FunctionAttribute(Name = "dbo.MyProc")]
[ResultType(typeof(ISingleResult<TestClass>))]
public ISingleResult<TestClass> GetMyProc([Parameter(Name = "SomeId", DbType = "Int")]int someId, [Parameter(Name = "AnotherId", DbType = "Int")]int anotherId)
{
var result = ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), someId, anotherId);
return (ISingleResult<TestClass>)(result.ReturnValue);
}
Had to add this class:
public class TestClass
{
[Column(Name = "UserId", DbType = "Int")]
public string UserId { get; set; }
}
This seems kind of ridiculous. Can I avoid creating TestClass, in this case?
Can I avoid creating TestClass, in this case?
Not with the framework you're currently using.
There are many other options out there. You could use ADO.NET directly; but then you're working with a DataTable instead of TestClass. You could use Dapper; where you'd still need TestClass but you wouldn't need GetMyProc. You could use a framework that generates the code, like an EF data model, or some other third-party framework.
But in general, the data needs marshaled into something.

Need help rewriting this Linq query to move it from code-behind to DAL as reusable object

I'm working to move my simple asp.net website to a three layer architecture. Currently I have Linq queries like the one below in my code-behind files. Basically this code snippet retrieves a collection of customer data from the database and then binds it to a grid control.
I'm wondering if someone can guide me on how to rewrite this in order to move it to my newly-created data access layer. I'm thinking I will turn it into a class (e.g. GetUserBoxesByStatus()) that can be reused throughout the site.
var boxes = from p in sbm.Packages
where p.UserID == CurrentUserId && p.StatusID > 1 && p.StatusID < 3
select new { p.PackageTag, p.PackageName, p.DateReceived, p.DateShipped };
GridView1.DataSource = boxes;
DataBind();
Some of the options that I've investigated but have not had success implementing are the following:
DataTable --- returning a DataTable seems like the best solution but it also appears to require a lot of potentially unecessarry code to define a table (isn't the data source already mapped in my Linq 2 Entities dbml?)
IEneuerable --- I think I could pass an IEnumerable list between the layers but after reading many tutorials about Linq I'm still a little lost
DTO --- Conceptually I think I understand what a DTO is but I am not clear on how to begin implementing this approach
POCO --- Again, the concept seems logical enough but I don't know how to put this into practice
I'm hoping someone here can look at my code example and propose how they would tackle this using one of the above or some other solution.
Create a class with the properties you need. Select into that class. Return a strongly-typed List (so that the query is actually performed in the DAL, not in your view). Bind your data source to the list.
public class PackageViewModel
{
public string Tag { get; set; }
public string Name { get; set; }
public DateTime Received { get; set; }
public DateTime Shipped { get; set; }
}
DAL
public List<PackageViewModel> GetUserBoxesByStatus( int userID, int minStatus, int maxStatus )
{
return sbm.Packages
.Where( p => p.UserID == userID
&& p.StatusID > minStatus
&& p.StatusID < maxStatus )
.Select( p => new PackageViewModel
{
Tag = p.PackageTag,
Name = p.PackageName,
Received = p.DateReceived,
Shipped = p.DateShipped
})
.ToList();
}

How do you bind a linq-to-entities query that contains a join to a writable datagridview?

This question, although similar to others, doesn't seem to be a duplicate. If it is, please clarify and I will be happy to merge.
I want to bind to a writable DataGridView using a linq-to-entities query containing a join. The model is as follows:
The denormalized DataGridView should be bound like so:
The following code binds but results in a readonly DataGridView because the linq-to-entities query returns an anonymous type (see this post). I'm at an impasse because I think I need the anonymous type to do the denormalization.
var query = from t in iDictionaryContext.DisplayTexts
from l in iDictionaryContext.Languages
where
t.LanguageID == l.LanguageID
select new
{
Key = t.DisplayKey,
Text = t.DisplayText1,
Language = l.LanguageName
};
I also tried the solution suggested here but it seems to apply to linq-to-sql but not to linq-to-entities. When setting the bindingsource.datasource to the linq-to-entities query, an exception is thrown reading "Only parameterless constructors and initializers are supported in LINQ to Entities."
Thank you for your advice,
Tim
Just define presentation type like that. You don't have to pass objects in constructor:
public class LanguageDisplayTextPresentation
{
public int Key { get; set; }
public string Text { get; set; }
public string Language { get; set; }
}
and then
var query = from t in iDictionaryContext.DisplayTexts
from l in iDictionaryContext.Languages
where
t.LanguageID == l.LanguageID
select new LanguageDisplayTextPresentation
{
Key = t.DisplayKey,
Text = t.DisplayText1,
Language = l.LanguageName
};

Resources