I am trying to access a stored procedure that retrieves a page using an id.
But I am getting an error:
Error 1 Cannot implicitly convert type
'System.Data.Entity.Core.Objects.ObjectResult<StorePageCMS.Models.mn_StorePage_Select_One_Result>' to 'StorePageCMS.Models.StorePage'
I am not sure how to fix this. The stored precedure that comes from dbEntities from SQL Server, does take an int parameter.
Any help is much appreciated.
public StorePage Get(int StorePageID)
{
using (dbEntities db = new dbEntities())
{
StorePage storepage = db.mn_StorePage_Select_One(StorePageID);
if (storepage == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return storepage;
}
}
UPDATE
I rewrote the method this way:
public List<StorePage> Get(int StorePageID)
{
List<StorePage> storepagelist = new List<StorePage>();
using (dbEntities db = new dbEntities())
{
var results = db.mn_StorePage_Select_One(StorePageID).ToList();
foreach (var result in results)
{
var storepage = new StorePage()
{
StorePageID = result.StorePageID,
SPPreambleID = result.SPPreambleID,
Title = result.Title,
SEOTitle = result.SEOTitle,
ParentStorePageID = result.ParentStorePageID ?? -1,
Meta = result.Meta,
Image = result.Image,
ImageLink = result.ImageLink,
Blurb = result.Blurb,
RegionID = result.RegionID,
Footer = result.Footer
};
storepagelist.Add(storepage);
}
return storepagelist;
}
}
Does this looks more correct?
2 UPDATE
Does this looks correct?
If you're not using the Code First model of Entity Framework
Since StorePageCMS.Models.mn_StorePage_Select_One_Result has no conversion to StorePage, I'm assuming it's a stored procedure result. If that's a stored procedure result (of mn_StorePage_Select_One), you need to map it's result to the StorePage model instead in the EDMX designer.
Here, you'd need to say it returns a collection of StorePageCMS.Models.StorePage Entities.
Related
I currently have a project that I'm working on, which has a database connected to it. In said database I need to query some tables that don't have a relationship. I need to get a specific set of data in order to display it on my user interface. However I need to be able to reference the returned data put it into a list and convert it into json. I have a stored procedure that needs to just be executed against the context because it's retrieving data from many different tables.
I've tried using ExecuteSqlCommand but that doesn't work, because it returns -1 and can't put it into a list.
I've tried using linq to select the columns I want however it's really messy and I cannot retrieve the data as easily.
I've tried using FromSql, however that needs a model to execute against the context which is exactly what I don't want.
public string GetUserSessions(Guid memberId)
{
string sql = $"EXECUTE dbo.GetUserTrackByMemberID #p0";
var session = _context.Database.ExecuteSqlCommand(sql, memberId);
var json = JsonConvert.SerializeObject(session);
return json;
}
This is the ExecuteSqlCommand example, this returns -1 and cannot be put into a list as there will be more than one session.
public string GetUserSessions(Guid memberId)
{
var session = _context.MemberSession.Where(ms => ms.MemberId == memberId).Select(s => new Session() { SessionId =
s.SessionId, EventId = s.Session.EventId, CarCategory = s.Session.CarCategory, AirTemp = s.Session.AirTemp,
TrackTemp = s.Session.TrackTemp, Weather = s.Session.Weather, NumberOfLaps = s.Session.NumberOfLaps, SessionLength = s.Session.SessionLength,
Event = new Event() { EventId = s.Session.Event.EventId, TrackId = s.Session.Event.TrackId, Name = s.Session.Event.Name, NumberOfSessions =
s.Session.Event.NumberOfSessions, DateStart = s.Session.Event.DateStart, DateFinish = s.Session.Event.DateFinish, TyreSet = s.Session.Event.TyreSet,
Track = new Track() { TrackId = s.Session.Event.Track.TrackId, Name = s.Session.Event.Track.Name, Location = s.Session.Event.Track.Location, TrackLength
= s.Session.Event.Track.TrackLength, NumberOfCorners = s.Session.Event.Track.NumberOfCorners} } });
var json = JsonConvert.SerializeObject(session);
return json;
}
This is using Linq, however it's really messy and I feel there's probably a better way to do this, and then when retrieving the data from json it's a lot bigger pain.
public string GetUserSessions(Guid memberId)
{
var session = _context.MemberSession.FromSql($"EXECUTE dbo.GetUserSessionByMemberID {memberId}").ToList();
var json = JsonConvert.SerializeObject(session);
return json;
}
This is the ideal way I would like to do it, however since I'm using the MemberSession model it will only retrieve that data from the stored procedure which is in the MemberSession table, however I want data that is in other tables as well....
public string GetUserSessions(Guid memberId)
{
var session = _context.MemberSession.Where(ms => ms.MemberId == memberId).Include("Session").Include("Event").ToList();
var json = JsonConvert.SerializeObject(session);
return json;
}
I tried this way but because the Event table has no reference / relationship to MemberSession it returns an error.
As I've previously stated in the RawSql example I'm only getting the table data that is in the MemberSession table, no other tables.
There are no error messages.
using (var context = new DBEntities())
{
string query = $"Exec [dbo].[YOUR_SP]";
List<ResponseList> obj = context.Database.SqlQuery<ResponseList>(query).ToList();
string JSONString = JsonConvert.SerializeObject(obj);
}
My team have read-access to a database maintained by a different team. We have a number of scripts that only we run, and so they've never been added as sprocs to the database (nor do we want them to be).
In Entity Framework 6, is it possible to include a file in my model which contains a stored procedure, so that we can leverage the code generation in EF?
We'd much rather have our code look like:
using (var db = new DatabaseEntities())
{
var properlyTypedResult = db.GetEntriesThatStartWith(firstName);
}
than:
using (var db = new DatabaseEntities())
{
var rawResult = db.Database.ExecuteSqlCommand("SELECT * FROM dbo.Person WHERE FirstName LIKE '#p0%'", firstName);
var properlyTypedResult = CastAppropriately(rawResult);
}
The functionality appears to be missing, but I thought I'd check regardless, I'd expect it to be in the designer view,
right-click, Add New -> Function Import...
... but this only allows adding sprocs to the model that are already in the database.
I think you're forgetting about LINQ - the second example would be something like...
List<People> people = (List<People>)db.Person.Where(f => f.FirstName.StartsWith(firstname)).ToList();
This should be close to what you're looking for. Linq is your friend.
I couldn't find exactly what I was after. I decided to simply write my own code generation, and leverage as much of Entity Framework as I could.
With query string in hand, execute against the database appropriately, using a SqlDataAdapter, with a DataTable
e.g.,
using (var context = new DbContext())
{
var dataTable = new DataTable();
var connection = (SqlConnection)context.Database.Connection;
if (connection != null && connection.State == ConnectionState.Closed)
connection.Open();
using (var adapter = new SqlDataAdapter(queryString, connection))
adapter.Fill(dataTable);
}
The DataTable contains the resulting column names along with all their types, now all we have to do is generate the code for the object.
i.e.,
var objectBuilder = new StringBuilder();
objectBuilder.AppendLine("public class QueryResult");
objectBuilder.AppendLine("{");
foreach (DataColumn column in dataTable.Columns)
{
objectBuilder.AppendLine(String.Format("public {0} {1} { get; set; }", column.DataType.Name, column.ColumnName));
}
objectBuilder.AppendLine("}");
Finally, create an extension method on the context object:
i.e.,
private static string GetQueryString(string firstName)
{
return String.Format($"SELECT * FROM dbo.Person WHERE FirstName LIKE '{firstName}%'", firstName);
}
public static partial class DbContextExtensions
{
public static List<QueryResult> GetEntriesThatStartWith(this DbContext context, string firstName)
{
return context.Database.SqlQuery<QueryResult>(GetQueryString(firstName)).ToList();
}
}
Now, we can use this as a regular sproc call:
using (var db = new DbContext())
{
var properlyTypedResult = db.GetEntriesThatStartWith(firstName);
}
I try to get all data from collection into MongoDB server using C# driver.
The idea is connect to the server and get all collection than insert into list of class.
List<WatchTblCls> wts;
List<UserCls> users;
List<SymboleCls> syms;
public WatchTbl()
{
InitializeComponent();
wts = new List<WatchTblCls>();
users = new List<UserCls>();
syms = new List<SymboleCls>();
}
public async void getAllData()
{
client = new MongoClient("mongodb://servername:27017");
database = client.GetDatabase("WatchTblDB");
collectionWatchtbl = database.GetCollection<WatchTbl>("Watchtbl");
collectionUser = database.GetCollection<UserCls>("Users");
collectionSymbole = database.GetCollection<SymboleCls>("Users");
var filter = new BsonDocument();
using (var cursor = await collectionWatchtbl.FindAsync(filter))
{
while (await cursor.MoveNextAsync())
{
var batch = cursor.Current;
foreach (var document in batch)
{
wts.Add(new WatchTblCls(document["_id"], document["userId"], document["wid"], document["name"], document["Symboles"]));
}
}
}
}
I get this error under
wts.Add(new WatchTblCls(document["_id"], document["userId"], document["wid"], document["name"], document["Symboles"]));
Cannot apply indexing with [] to an expression of type 'WatchTbl'
I don't understand the reason behind using WatchTbl and WatchTblCls both together. Is WatchTblCls a model for the entity WatchTbl here? Im not sure.
In any case. If you go for aggregation and want to convert WatchTbl collection to WatchTblCls list, your desired solution might look like the following. I don't know the defiitions of the classes so I'm assuming:
var client = new MongoClient("mongodb://servername:27017");
var database = client.GetDatabase("WatchTblDB");
var collectionWatchtbl = database.GetCollection<WatchTbl>("Watchtbl");
var collectionUser = database.GetCollection<UserCls>("Users");
var collectionSymbole = database.GetCollection<SymboleCls>("Users");
var list = collectionWatchtbl.AsQueryable().Select(x => new WatchTblCls() {
id = x.id,
userId = x.userId,
.....
});
If you can use the same WatchTbl class and still want to load the full collection to a local List (which is definitely not a good idea):
List<WatchTbl> list = await collectionWatchtbl.Find(x => true).ToListAsync();
Can anyone tell where I make a mistake ? :( I want to insert a row using this. It's just not working. I also tried to use "context.SaveChanges();" but nothing changed. No insert at all, and no exception.
public List<string> Add_Address(string address, int selected_item)
{
List<string> list = new List<string>();
using(var context = new RSS_Reader_Database())
{
Address Address = new Address();
Category_Address Category_Address = new Category_Address();
Address.URL = address.ToString();
int max_id = Convert.ToInt32(context.Addresses.OrderByDescending(t => t.ID_Address).FirstOrDefault());
Category_Address.ID_Address = max_id;
Category_Address.ID_Category = selected_item+1;
var select_query = from t in context.Addresses select t.URL;
foreach (var element in select_query)
{
list.Add(element);
}
}
return list;
}
Edit: Following all Your advices, I made something that works. Looking at this code above, I have no idea what I was trying to do yesterday. Thanks a lot.
public List<string> Add_Address(string address, int selected_item)
{
List<string> list = new List<string>();
using(var context = new RSS_Reader_Database())
{
Address Address = new Address() { URL = address };
context.Addresses.Add(Address);
context.SaveChanges();
int max_id = context.Addresses.Max(u => u.ID_Address);
Category_Address Category_Address = new Category_Address() { ID_Address = max_id, ID_Category = selected_item + 1 };
context.Categories_Addresses.Add(Category_Address);
context.SaveChanges();
var query = from t in context.Addresses
select t.URL;
var data = query.ToList();
foreach (var element in data)
{
list.Add(element);
}
}
return list;
}
Saving with Entity Framework generally works like this. Using your above code as a starting point.
using(var context = new RSS_Reader_Database())
{
Address address = new Address();
// Set address properties
context.Addresses.Add(address);
context.SaveChanges();
}
You need to add the object to the DbSet<T> where T is the type of the entity that is defined on the DbContext. You then need to call SaveChanges() on the context.
I would suggest reading this. It is an easy to follow introduction to Entity Framework.
Not sure exactly what you are trying to do.
But if you are expecting to insert the data by the list.Add(element); command it won't work.
If you are planning to insert data into the same DB, you need to use one property from the context to represent the List collection add a new element on this property.
Something like:
context.Lists.Add(element);
if you want retrieve data, you should not call SaveChanges() !,
try get all values from one query like this:
List<string> select_query = (from t in context.Addresses select t.URL).ToList();
I have a code that gets all products from my DB:
using (var entities = new DataEntities())
{
var products = entities.Products.AsQueryable();
if (!string.IsNullOrEmpty(nameFilter))
{
products = products.Where(o => o.Name.Contains(nameFilter));
}
var result = products.Select(ProductBuilder.CreateProductDto);
return result.ToList();
}
CreateProductDto method:
public static ProductDto CreateProductDto(this Product product)
{
return new ProductDto
{
Id = product.Id,
Name = product.Name,
IsEnabled = product.IsEnabled,
KeyPairDto = new KeyPairDto()
{
Id = product.KeyPair.Id,
EncryptedPrivateExponent = product.KeyPair.EncryptedPrivateExponent,
Modulus = product.KeyPair.Modulus,
PublicExponent = product.KeyPair.PublicExponent,
},
};
}
It works fine on my colleaugue's machine. But I get EntityCommandExecutionException with the folloing inner exception: There is already an open DataReader associated with this Command which must be closed first. when trying to access product.KeyPair.
Interesting thing is that if I refresh product.KeyPair via Debugger - it loads fine.
Add
MultipleActiveResultSets=true
to the provider part of the connection string within your entity framework connection string (i.e. the part the defines the data source, initial catalog, etc)