Hello, I'm currently trying to show a table in an Android base App. however, my question is regarding:
var db = new SQLiteAsyncConnection(Database.DatabasePath.DB_Path);
foreach ( var N in db.Table<Database.Inventory>() )
{
InventoryItems.Add(new Store_Listing { Id = N.Id,
Description = N.Description, Style = N.Style });
This part of the code that is taking an error of:
foreach statement cannor operate on variables of type 'AsyncTableQuery< ... > ' because 'AsyncTableQuery< ... >' does not contain a public instance for 'GetEnumerator'
foreach ( var N in db.Table<Database.Inventory>() ) "
I have looked into the Database.Inventory Class, and it is set to public class, and all the elements are exactly as the SQLite database (Type 3) table.
Honestly I don't really know what is wrong.
There are no issues connecting the database .db3, but these error is unknown to me since I'm quite new to the SQLite and Android.App Dev.
This is the code for the Database.Inventory:
using System;
using System.Collections.Generic;
using System.Text;
using SQLite;
namespace Inventory.Database
{
[Table("Inventory")]
public class Inventory
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
public string Style { get; set; }
}
}
Thank You for your feedback in advance.
You are calling a new instance of SQLiteAsyncConnection, which uses async instructions for all its methods (where needed). In the SQLite NuGet source code, you will find that Table<T> returns a variable of type AsyncTableQuery. AsyncTableQuery does not implement or inherit anything. It's a stand-alone class, which means it cannot access the method GetEnumerator that it is expecting to access for a foreach statement.
So, in your code where you have:
var db = new SQLiteAsyncConnection(Database.DatabasePath);
foreach ( var N in db.Table<Database.Inventory>() ) // Table<T> does *not* return a List<T>!!
{
InventoryItems.Add(new Store_Listing
{
Id = N.Id,
Description = N.Description,
Style = N.Style
});
}
You're trying to access what you think is a List, but is actually an AsyncTableQuery.
How to get around this
If you look at the AsyncTableQuery class, it has a ToListAsync method, which converts the AsyncTableQuery object to a List<T> object. Simply calling this will convert your Table<T> to a List<T> like so:
var db = new SQLiteAsyncConnection(Database.DatabasePath);
var myList = await db.Table<Database.Inventory>().ToListAsync();
// TODO: Add a null or empty check to prevent NullExceptions.
foreach(var N in myList)
{
// Do your stuff
}
var results = await db.Table<Database.Inventory>();
var query = conn.Table<Database.Inventory>();
query.ToListAsync().ContinueWith((t) =>
{
foreach (var N in t.Result)
{
// code from your foreach loop
}
});
Related
I have some code I am trying to convert. I don't have these ObjectResult and ObjectContext anymore
This is what I did have:
public virtual ObjectResult<string> GetTransData(string iN_MEM_ID)
{
var iN_MEM_IDParameter = iN_MEM_ID != null ?
new ObjectParameter("IN_MEM_ID", iN_MEM_ID) :
new ObjectParameter("IN_MEM_ID", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<string>("GetTransData", iN_MEM_IDParameter);
}
Since I need a List to be returned from a caller ( it is sent back as json data )
This is what I am trying to build
public virtual List<string> GetTransData(string iN_MEM_ID)
{
var iN_MEM_IDParameter = iN_MEM_ID != null ?
new SqlParameter("IN_MEM_ID", iN_MEM_ID) :
new SqlParameter("IN_MEM_ID", typeof(string));
Clinical_CaseTrakker_Context clinical = new Clinical_CaseTrakker_Context();
List<string> offLine = clinical.string.FromSql("EXECUTE CT.GetTransData {0}", iN_MEM_IDParameter);
return offLine;
}
Notice that I am stuck with clinical.string i can't do that , but I am not sure how to take dbcontext instance and run FromSql to execute sql and return to List
In EF Core, it is not possible to use the FromSql method to return a subset of properties (a projection) directly from the database.
You are required to define a some model and a DbSet for that class
public class Foo
{
public string Bar { get; set; }
}
then declare in your context
public DbSet<Foo> Foos { get; set; }
and use it like:
using (var context = new Clinical_CaseTrakker_Context())
{
var offLine = context.Foos
.FromSql($"EXECUTE CT.GetTransData {iN_MEM_IDParameter}")
.Select(x => x.Bar)
.ToList();
return offLine;
}
Your Context needs a virtual DbSet<string> ResultStrings { get; set; } that you can call upon and put the result in. (This does not work, see this post or Roman Marusyk comment below)
EDIT: Your Context needs a virtual DbSet<ResultEntity> ResultEntities { get; set; } that you can call upon and put the result in.
Then you can do return clinical.ResultEntities.FromSql("EXECUTE CT.GetTransData {0}", iN_MEM_IDParameter").toList() to fill the set.
Considering the ResultEntity has an Id and a value property, you can do ResultEntities.Select(e => e.value).toList() to extract a list of strings from the set.
I'm trying to do what I thought would be a very simple think using Linq lambda, it probably is, but I can't find an example in any tutorial.
I have a simple class with a few properties. I want to get a list of one of the properties based on the value on another value in that class.
Below is an example of the code, using Linq to get the correct results:
public class Client
{
public int ClientId { get; set; }
public int ClientWorth { get; set; }
public strin ClientName { get; set; }
}
.
.
.
.
List<Client> allClients = this.GetAllClients();
List<string> richClients = (
from c in allClients
where c.ClientWorth > 500
select c.ClientId.ToString()).ToList();
Can someone tell me how to do this using a lambda
I can do the following:
List<Clients> richClients = allClients.Where(x => x.ClientWorth >500)
Which give me a list of all clients, but I would like to get a string list back with just the client ids.
After filtering by client worth value you should project results - i.e. select only client id value:
allClients.Where(c => c.ClientWorth > 500).Select(c => c.ClientId.ToString()).ToList()
Further reading: Enumerable.Select
In my MVC web application, I have linq query that feth the record from database, I want to display that record on view using viewmodel. I have tried with following code.
[HttpGet]
public ActionResult CreatePDF()
{
RentalAgreementEntities db = new RentalAgreementEntities();
String strSession1 = "39726-10275-6027589725",strStatus = "Y",strUserType = "L";
var q = (from um in db.User_Master
join ut in db.UserType_Master on um.US_SerialNo.ToString() equals ut.UT_UserNo
join pu in db.PropertyUser_Master on ut.UT_SerialNo.ToString() equals pu.PU_UserNo
join pr in db.Property_Master on pu.PU_PropertyNo equals pr.PR_SerialNo.ToString()
where pr.PR_MakerID == strSession1
&& ut.UT_Status == strStatus
&& ut.UT_UserType == strUserType
select new
{
um.US_FirstName,
um.US_LastName
}
).AsEnumerable().Select(um => new User_Master {
US_FirstName = um.US_FirstName.ToString(),
US_LastName=um.US_LastName
}).ToList();
var myviewmodel=new viewmodelPDF()
{
lsusermaster=q.ToList();
}
return View("pdfgenerationvw",myviewmodel);
}
I also created viemodel to manage all model's for to display on a view (Here, Just one model access code).
public class viewmodelPDF
{
public List<User_Master> lsusermaster { get; set; }
}
My model class, for which I am going to fetch record from database.
public partial class User_Master
{
public string US_FirstName { get; set; }
public string US_LastName { get; set; }
public int US_SerialNo { get; set; }
}
//Other Models
Now my problem is that, In my action code , when I am trying to assign query result to the lsusermaster of viewmodel then it gives compiler error as belows.
I don't know, why this compile error is thrown, How can I assign query result to viemodel property?
Try this:
var myviewmodel=new viewmodelPDF()
{
lsusermaster=q.ToList()
};
When you are using an object initializer in C#, you can't use ; between the properties, you use it at the end of the initializer
So just remove the ; (or use a ,, as suggested), and move it to the end of the initializer block
var myviewmodel=new viewmodelPDF()
{
lsusermaster=q.ToList()
};
Using a , works even if there are no more properties... it "looks" bad, but it makes easier to add new properties should you ever need them... if the code is final, I'd not use it, but that's personal preference
I created a table in my designer view with 4 columns. I'd like to add others columns manually (because it'll be add according the data stored in DB).
I would like to create the link between the data from DB and the table so I did this :
private void LoadSiteDataSource()
{
CVaultDataSource.Rows.Clear();
if (this.Site != null)
{
var sitesDB = from sites in this.Site
select sites.KEY;
foreach (var item in sitesDB)
{
CVaultDataSource.Rows.Add(item);
}
}
}
But I have this error :
Could not find an implementation of the query pattern for source type System.ComponentModel.ISite. 'Select not found'.
I've look the differents topics about this error but I could not find something to fix it.
I'm already using this function which works :
private void LoadDataSource()
{
CVaultDataSource.Rows.Clear();
if (this.BaseFilters != null)
{
var filters = from filterBase in this.BaseFilters
orderby filterBase.EVPTCODE
select new object[] { filterBase.CVAULTCODE, filterBase.EVPTCODE, filterBase.EVPTDESIGNATION, filterBase.DURATION, filterBase.ETDTIME };
foreach (var item in filters)
{
CVaultDataSource.Rows.Add(item);
}
}
}
Does someone know why it does not work ?
I just forget to declare this :
public List<SITE> Sites { get; private set; }
That's why it did not work.
I have this working in my controller, but I want to follow best practices and put my database logic in Model.
I want to put all database logic (select, update, delete, insert) to MODEL, therefore I create methods in my model.
My method for retrieving the data:
public IQueryable<ChatLogsNameViewModel> getChatLogWithName()
{
using (var db = new ChatLogContext())
{
var list = (from b in db.ChatLogs
select new ChatLogsNameViewModel()
{
UserProfile = b.UserProfile,
Message = b.Message,
Time = b.Time
});
return list;
}
}
This is my modelView:
public class ChatLogsNameViewModel
{
public UserProfile UserProfile { get; set; }
public string Message { get; set; }
public DateTime Time { get; set; }
}
I call my getChatLogWithName() method in my controller like this:
List<ChatLogsNameViewModel> items = null;
using (var dba = new ChatLogContext())
{
items = dba.getChatLogWithName().ToList();
return View(items);
}
Error I get is:
The operation cannot be completed because the DbContext has been disposed.
What is the proper way to do this? I just want to pass collection (all records from 2 tables via join) to controller.
To ensure that the DBContext is not getting referenced after disposal. How about returning a list so you dont have to call .ToList():
public List<ChatLogsNameViewModel> getChatLogWithName()
{
using (var db = new ChatLogContext())
{
var list = (from b in db.ChatLogs
select new ChatLogsNameViewModel()
{
UserProfile = b.UserProfile,
Message = b.Message,
Time = b.Time
});
return list.ToList();
}
}
and
items = dba.getChatLogWithName();
Or
Since it appears that dba is the same as db, couldn't you change your code to use the dba instance which won't get disposed until the end of your using statement within your controller.
public IQueryable<ChatLogsNameViewModel> getChatLogWithName()
{
var list = (from b in this.ChatLogs
select new ChatLogsNameViewModel()
{
UserProfile = b.UserProfile,
Message = b.Message,
Time = b.Time
});
return list;
}
Lifetime - DbContext
The lifetime of the context begins when the instance is created and
ends when the instance is either disposed or garbage-collected. Use
using if you want all the resources that the context controls to be
disposed at the end of the block. When you use using, the compiler
automatically creates a try/finally block and calls dispose in the
finally block.
The problem was when the inner using got disposed, it invalidated the DbContext. So you need to use .ToList() to save the query result in memory.
Suppose getChatLogWithName is defined in the class called Repo, you can change the controller logic to something like this:
var repo = new Repo();
var items = repo.getChatLogWithName().ToList();
Or move .ToList() to getChatLogWithName.
Btw, you should not use the nested DbContexts cope, in your controller, you don't have to wrap it using another DbContextscope.