How can I count total item in an object/record and count only the value = true - sql

var obj = (from r in db.Module_Completion
.Where(r => r.star_id == User.Identity.Name)
select new
{
r.adv_stud_success,
r.important_policies,
r.technology,
r.finances,
r.resources,
r.student_life,
r.next_steps
}).FirstOrDefault();
obj = {true, false, false , true,...};
This is only one record that I query from database by using Linq
The reason is I would like to display Finsished 2 of 7 , that is why I need to count items in a record.
Thank you in advance!
public partial class Module_Completion
{
public int module_completionId { get; set; }
[StringLength(10)]
public string star_id { get; set; }
public bool adv_stud_success { get; set; }
public bool important_policies { get; set; }
public bool technology { get; set; }
public bool finances { get; set; }
public bool resources { get; set; }
public bool student_life { get; set; }
public bool next_steps { get; set; }
}
After I can store numbers in variable, then I would like to display like this"Finished 2 of 7"

So Every ModuleCompletion contains several Boolean properties. If the value of such a property is true, you consider the item to be "finished".
You want to count the number of finished items in a ModuleCompletion.
The proper method would be to add a property to class ModuleCompletion.
public int FinishedCount => ...
If you can't do this, for instance because ModuleCompletion represents the columns of a table in a database, then consider to add an extension method. If you are not familiar with extension methods, read Extension Methods demystified
public static int CountFinished(this ModuleCompletion moduleCompletion)
{
// TODO: implement
}
Usage would be:
ModuleCompletion x = ...
int finished = x.CountFinished();
This would work if your ModuleCompletion is in local process. However, if you want to do this database side (as queryable), this won't work: your database wouldn't know method CountFinished.
If you want to let the database do this, you could change your Select method:
int finishedCount = db.ModuleCompletions
.Where(completion => completion.star_id == User.Identity.Name)
.Select(completion =>
completion.adv_stud_success ? 1 : 0 +
completion.important_policies ? 1 : 0 +
completion.technology : 1 : 0 +
...)
.FirstOrDefault();
This looks rather ugly. Luckily we can create an extension method of IQueryable<ModuleCompletion>, such that you can use it as any other LINQ method:
public static IQueryable<int> ToFinishedCount(this IQueryable<ModuleCompletion> moduleCompletions)
{
return moduleCompletions.Select(completion =>
completion.adv_stud_success ? 1 : 0 +
completion.important_policies ? 1 : 0 +
completion.technology : 1 : 0 +
...);
}
This query can be translated into a language that your DBMS understands. Usage would be much easier to understand, much easier to reuse, unit test and modify:
int finishedCount = db.ModuleCompletions
.Where(completion => completion.star_id == User.Identity.Name)
.ToFinishedCount()
.FirstOrDefault();

My solution involves 2 parts first. Create a ViewModel to get the number of completed object that associates with the class that goes:
public class ModuleCompletesVM
{
public Module_Completion Module_Completion { get; set; }
public int Completed { get
{
return (Convert.ToInt32(Module_Completion.stud_success) +
Convert.ToInt32(Module_Completion.important_policies) +
Convert.ToInt32(Module_Completion.technology) +
Convert.ToInt32(Module_Completion.finances) +
Convert.ToInt32(Module_Completion.resources) +
Convert.ToInt32(Module_Completion.next_steps) +
Convert.ToInt32(Module_Completion.student_life));
}
}
}
Note that this View Model would calculate the number of completed subject of each Module_Completion Class and then from your controller. You just need to do something like this
var model= from s in db.Module_Completion
select new ModuleCompletesVM
{
Module_Completion = s
};
You can also achieve this by creating a function in SQL database as well. Another piece of advice is that, do consider stop using underscrore in your data table and data field. Follow the latest convention, the next person who take over your code will appreciate that.

I have an approach where you can have the total finished as property. Here is an example
public partial class Module_Completion
{
private bool _adv_stud_success;
private bool _important_policies;
private bool _technology;
private bool _finances;
private bool _resources;
private bool _student_life;
private bool _next_steps;
public int module_completionId { get; set; }
[StringLength(10)]
public string star_id { get; set; }
public bool adv_stud_success
{
get { return _adv_stud_success; }
set {
_adv_stud_success = value;
if (_adv_stud_success)
{
total_finsihed += 1;
}
}
}
public bool important_policies
{
get { return _important_policies; }
set
{
_important_policies = value;
if (_important_policies)
{
total_finsihed += 1;
}
}
}
public bool technology
{
get { return _technology; }
set
{
_technology = value;
if (_technology)
{
total_finsihed += 1;
}
}
}
public bool finances
{
get { return _finances; }
set
{
_finances = value;
if (_finances)
{
total_finsihed += 1;
}
}
}
public bool resources
{
get { return _resources; }
set
{
_resources = value;
if (_resources)
{
total_finsihed += 1;
}
}
}
public bool student_life
{
get { return _student_life; }
set
{
_student_life = value;
if (_student_life)
{
total_finsihed += 1;
}
}
}
public bool next_steps
{
get { return _next_steps; }
set
{
_next_steps = value;
if (_next_steps)
{
total_finsihed += 1;
}
}
}
/* This property is storing the finished count */
/* using System.ComponentModel.DataAnnotations.Schema; */
[NotMapped]
public int total_finsihed { get; set; }
}
After that you can do the following
var obj = (from r in db.Module_Completion
.Where(r => r.star_id == User.Identity.Name)
select new
{
r.total_finsihed
}).FirstOrDefault();
/* if the technology, finance, resources are true then */
/* obj = {3}; */

Related

Xamarin.Forms: Cannot connect to database

I have this database structure:
public class QRDatabase
{
readonly SQLiteAsyncConnection _database;
public QRDatabase(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<db_QRCODE_Type>().Wait();
}
public Task<List<db_QRCODE_Type>> GetQRCode()
{
return _database.Table<db_QRCODE_Type>().ToListAsync();
}
public Task<int> SaveQRCode(db_QRCODE_Type note)
{
if (note.ID != 0)
{
return _database.UpdateAsync(note);
}
else
{
return _database.InsertAsync(note);
}
}
public Task<int> DelteQRCode(db_QRCODE_Type note)
{
return _database.DeleteAsync(note);
}
}
This uses this type:
public class db_QRCODE_Type
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; } // Identificator of column
public string firstName { get; set; } // firstname
public string lastName { get; set; } // firstname
public byte[] qrBytes { get; set; } //qr code in bytes
}
Then, in the class where I need the DB I am doing this from the tutorial here:
https://learn.microsoft.com/de-de/xamarin/get-started/quickstarts/database?pivots=windows
static QRDatabase database;
static string nameOfDB = "01db_qrs_q2go.db3";
public static QRDatabase Database
{
get
{
if (database == null)
{
database = new QRDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameOfDB));
}
return database;
}
}
However, I am not quite sure how this works since I am never calling "Database" even though this is where the database is supposed to be initiliased.
Now, when I try to write to the database:
db_QRCODE_Type entry = new db_QRCODE_Type();
entry.firstName = entry_firstname.Text;
entry.lastName = entry_lastname.Text;
entry.qrBytes = qrCodeBytes;
try
{
await database.SaveQRCode(entry);
}
catch
{
DependencyService.Get<IMessage>().LongAlert("Etwas hat nicht funktioniert, bitte versuche es noch einmal. Fehlercode: DB_665h");
}
It fails saying it is not set reference to an instance and goes into the catch block. I am doing everything as in the tutorial. Why is this happening?
Thank you!

Retrieve values from SQL database - EF

I'm trying to figure out how to pull values from a SQL database and display this in a razor view.
I have the following class using Entity Framework (I believe)
public class EventLog
{
[Key]
public int Id { get; set; }
public int EventId { get; set; }
public int MaxDelegates { get; set; }
public string Code { get; set; }
public DateTime End { get; set; }
public string Title { get; set; }
}
And I want to map title to DBTitle in the following model:
public class CourseDetailVM : CourseDetailSummaryVM
{
public EventLog DBTitle { get; set; }
}
I then want to see this in the following view:
#using TSW.Web.Helpers
#model TSW.Web.ViewModels.CourseDetailVM
#{
Layout = "~/Views/_Master.cshtml";
}
#Model.DBTitle.Title;
I have the following controller already in place (sorry for the length I plan to reduce this down):
public class CourseDetailController : BaseRenderController<CourseDetailPageDT>
{
private readonly ISitePageFactory _pageFactory = null;
private readonly IEventService _eventService = null;
public CourseDetailController(IEventService eventService, ISitePageFactory pageFactory)
{
_pageFactory = pageFactory;
_eventService = eventService;
}
public async Task<ActionResult> CourseDetail()
{
var homepage = _pageFactory.GetCurrentHomepage();
var model = Mapper.Map<CourseDetailVM>(CurrentContent);
model.Email = homepage.ContactEmail;
model.PhoneNumber = homepage.HeaderPhoneNumber;
model.InnerPageHeader.ShowHeading = true;
model.InnerPageHeader.Title = model.PageTitle;
if (model.Categories.Count == 1)
{
var categoryTagId = model.Categories.First().Id;
var contentTypeAlias = DocumentTypeHelper.GetDocumentTypeAlias<CourseListingPageDT>();
var courseCategoryPage = Umbraco.TypedContentAtXPath($"//{contentTypeAlias}")
.FirstOrDefault(x => x.GetPropertyValue<int>(Constants.DocumentTypes.CourseListingPage.Category) == categoryTagId);
if (courseCategoryPage != null)
{
model.InnerPageHeader.BackLink = Mapper.Map<LinkItem>(courseCategoryPage.Id);
}
}
try
{
model.Events = await _eventService.GetEventsForCourse(CurrentContent.AdministrateId);
}
catch (Exception ex)
{
model.Events = new StaticPagedList<Event>(Enumerable.Empty<Event>(), 1, 1, 0);
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
if (CurrentContent.Graphic != 0)
{
model.InnerPageHeader.Graphic = Mapper.Map<CtaItem>(CurrentContent.Graphic);
}
return View(model);
}
}
I've tried every suggestion I can google to add the mapping in the controlling but can't get my head around this simple function of pulling the value from a SQL database into the razor view.
Could anyone help me out?

Why, in Entity Framework 6, when copying a domain model to another domain model, does the original object get updated when changing the copy's values?

Below are the necessary models for this example.
public class OrderDetailPackageVM
{
public OrderDetail OrderDetail { get; set; }
public Package Package { get; set; }
}
public class Package
{
public Package()
{
this.PackageProducts = new List<PackageProduct>();
}
public int PackageId { get; set; }
public int WebsiteId { get; set; }
public virtual List<PackageProduct> PackageProducts { get; set; }
}
public class PackageProduct
{
public int PackageProductId { get; set; }
public int PackageId { get; set; }
public virtual Package Package { get; set; }
public int ProductId { get; set; }
public virtual Product Product { get; set; }
public int ProductCategoryId { get; set; } // not a FK but data only
public virtual ProductCategory ProductCategory { get; set; }
}
In the following code snippet, you should see the problem illustrated.
List<OrderDetailPackageVM> pkgs = (from odx in db.OrderDetails
from pax in db.Packages
where odx.OrderId == orderId
&& pax.PackageId == odx.PackageId
&& odx.PricelistProduct.Product.isStandalone == true
&& pax.WebsiteId == websiteId
select new OrderDetailPackageVM
{
Package = pax,
OrderDetail = odx
}).AsNoTracking().ToList();
List<OrderDetailPackageVM> packages = new List<OrderDetailPackageVM>();
packages.AddRange(pkgs);
//also tried packages = pkgs;
//also tried packages.injectFrom(pkgs) //from omu valueInjector - similar to automapper
At this point in my watch we see:
pkgs.Package.PackageProducts.Count = 6;
packages.Package.PackageProducts.Count = 6;
foreach (OrderDetailPackageVM pac in packages)
{
pac.Package.PackageProducts.RemoveAll();
}
At this point in my watch we see:
pkgs.Package.PackageProducts.Count = 0;
packages.Package.PackageProducts.Count = 0;
When I was expecting to see:
pkgs.Package.PackageProducts.Count = 6;
packages.Package.PackageProducts.Count = 0;
So why is the original object changing when the changes are applied to the copy. I do not remember this behavior in earlier versions of EF?
And what is the work-around for this?
I thought doing a select with NoTracking was supposed to 'Free' the data in the model from EF change tracking?
Thanks so much for helping me understand this behavior.
THE FOLLOWING IS THE METHOD I USED TO SOLVE THIS ISSUE BASED ON FEEDBACK BELOW:
public static T DeepClone<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
You do not create new objects. You place the existing objects in a new list. You would need to create completely new objects and copy the values manually. This is also known as a deep copy or doing a clone ( see ICloneable ).
If omu valueInjector assigns property for property it assigns the list of object a to the list of object b. As it is a reference type, it's actually the same. If you want to have new objects you have to make a deep copy. See Deep cloning objects for more info.
The behavior has actually nothing with tracking the changes from an EF view. You work with reference types.
A small sample program:
using System;
using System.Collections.Generic;
namespace _28637405 {
class Outer {
public string MyProperty { get; set; }
}
class Program {
static void Main( string[] args ) {
var listOne = new List<Outer>();
for ( int i = 0; i < 10; i++ ) {
listOne.Add( new Outer { MyProperty = "obj #" + (i + 1) } );
}
// first line
Console.WriteLine( listOne[0].MyProperty );
var listTwo = new List<Outer>();
listTwo.AddRange( listOne );
// second line
Console.WriteLine( listTwo[0].MyProperty );
listTwo[0].MyProperty = "Changed";
// third and fourth line
Console.WriteLine( listOne[0].MyProperty );
Console.WriteLine( listTwo[0].MyProperty );
var listThree = new List<Outer>();
foreach ( var obj in listOne )
listThree.Add( new Outer { MyProperty = obj.MyProperty } );
listThree[0].MyProperty += " again";
// lines 5,6,7
Console.WriteLine( listOne[0].MyProperty );
Console.WriteLine( listTwo[0].MyProperty );
Console.WriteLine( listThree[0].MyProperty );
}
}
}
The ouutput it produces:
obj #1
obj #1
Changed
Changed
Changed
Changed
Changed again
The class Outer would look like this if it would implement ICloneable:
class Outer : ICloneable {
public string MyProperty { get; set; }
public object Clone() {
return new Outer { MyProperty = this.MyProperty };
}
}
Usage would be (including a cast to Outer ):
var newObject = existingObject.Clone() as Outer;

NHibernate Mapping Property Which Depends on Another Property

I have the following class:
public class Widget {
public virtual int Id { get; set; }
[Required]
public virtual WidgetType Type { get; set; }
public virtual string SerializedParameters {
get {
return new XmlSerializer(Parameters.GetType()).Serialize(Parameters);
} set {
Parameters = new XmlSerializer(Assembly
.LoadFrom(Server.MapPath(Type.ModelAssembly))
.GetType(Type.ModelClass)
).Deserialize(value);
}
}
private object _parameters;
public virtual object Parameters {
get {
if (_parameters == null)
_parameters = Activator.CreateInstance(Assembly
.LoadFrom(Server.MapPath(Type.ModelAssembly))
.GetType(Type.ModelClass)
);
return _parameters;
} set { _parameters = value; }
}
}
The Parameters property is not mapped to the database but the SerializedParameters property is. However when it tries to get the information from the database and set the SerializedParameters (which subsequently sets the Parameters) the Type property is null and therefore an exception is thrown. I guess this depends on the order in which NHibernate sets the properties for the Widget but i can't get it to work.
I was wondering if there was a way around this. Appreciate the help. Thanks
moved the deserialization in the getter from the setter because as you said the type is not there yet
public class Widget
{
public virtual int Id { get; set; }
public virtual WidgetType Type { get; set; }
private string _serializedParameters;
private virtual string SerializedParameters {
get
{
return new XmlSerializer(Parameters.GetType()).Serialize(Parameters);
}
set
{
_serializedParameters = value;
}
}
private object _parameters;
public virtual object Parameters
{
get
{
if (_parameters == null)
{
if (!string.IsNullOrEmpty(serializedParameters))
{
// code to deserialize the Parameters and set to Parameters
_parameters = new XmlSerializer(Assembly
.LoadFrom(Server.MapPath(Type.ModelAssembly))
.GetType(Type.ModelClass)
).Deserialize(value);
}
else
{
// no existing parameters, then create new object
_parameters = Activator.CreateInstance(Assembly.LoadFrom(Server.MapPath("~/bin/" + widget.Type.ParametersAssembly + ".dll")).GetType(widget.Type.ParametersClass));
}
}
return _parameters;
}
set { _parameters = value; }
}
}

NHibernate FetchMode.Lazy

I have an object which has a property on it that has then has collections which i would like to not load in a couple situations. 98% of the time i want those collections fetched but in the one instance i do not. Here is the code I have... Why does it not set the fetch mode on the properties collections?
[DataContract(Name = "ThemingJob", Namespace = "")]
[Serializable]
public class ThemingJob : ServiceJob
{
[DataMember]
public virtual Query Query { get; set; }
[DataMember]
public string Results { get; set; }
}
[DataContract(Name = "Query", Namespace = "")]
[Serializable]
public class Query : LookupEntity<Query>, DAC.US.Search.Models.IQueryEntity
{
[DataMember]
public string QueryResult { get; set; }
private IList<Asset> _Assets = new List<Asset>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Asset> Assets { get { return _Assets; } set { _Assets = value; } }
private IList<Theme> _Themes = new List<Theme>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Theme> Themes { get { return _Themes; } set { _Themes = value; } }
private IList<Affinity> _Affinity = new List<Affinity>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Affinity> Affinity { get { return _Affinity; } set { _Affinity = value; } }
private IList<Word> _Words = new List<Word>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Word> Words { get { return _Words; } set { _Words = value; } }
}
using (global::NHibernate.ISession session = NHibernateApplication.GetCurrentSession())
{
global::NHibernate.ICriteria criteria = session.CreateCriteria(typeof(ThemingJob));
global::NHibernate.ICriteria countCriteria = session.CreateCriteria(typeof(ThemingJob));
criteria.AddOrder(global::NHibernate.Criterion.Order.Desc("Id"));
var qc = criteria.CreateCriteria("Query");
qc.SetFetchMode("Assets", global::NHibernate.FetchMode.Lazy);
qc.SetFetchMode("Themes", global::NHibernate.FetchMode.Lazy);
qc.SetFetchMode("Affinity", global::NHibernate.FetchMode.Lazy);
qc.SetFetchMode("Words", global::NHibernate.FetchMode.Lazy);
pageIndex = Convert.ToInt32(pageIndex) - 1; // convert to 0 based paging index
criteria.SetMaxResults(pageSize);
criteria.SetFirstResult(pageIndex * pageSize);
countCriteria.SetProjection(global::NHibernate.Criterion.Projections.RowCount());
int totalRecords = (int)countCriteria.List()[0];
return criteria.List<ThemingJob>().ToPagedList<ThemingJob>(pageIndex, pageSize, totalRecords);
}