OK, I am mostly a LAMP developer so I am new to the entity framework. However, I am familiar with the basics in LINQ and have generated a entity model from my DB. Now here is my requirement:
I have a datagrid on a WinForm that will be refreshed from a data source on a remote server every few seconds as changes to the dataset are made from other sources. Obviously, I'd like to construct a lambda expression to get the right anonymous type to satisfy the columns that needs to be shown in my datagrid. I have done this and here is the result (I'm using a custom datagrid control, btw):
And my code thus far:
Models.dataEntities objDB = new Models.dataEntities();
var vans = from v in objDB.vans
select v;
gcVans.DataSource = vans;
OK, so now I have my basic data set. One problem I had is that the "Status" column will show a calculated string based on several parameters in the data set. I added this to my entities via a partial class. As you can see in the screenshot, this is working correctly:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication1.Models {
public partial class van {
public string van_status {
get {
if (this.is_offline == 1) {
return "Offline";
} else if (this.is_prayer_room == 1) {
return "In Prayer Room";
} else {
return "TODO: Create statuses";
}
}
}
}
}
This added property works fine. However, the second I try to project the status in an anonymous type so I can also retrieve the school name, I get an error:
Models.dataEntities objDB = new Models.dataEntities();
var vans = from v in objDB.vans
select new {
van_name = v.van_name,
school_name = v.school.school_name,
capacity = v.capacity,
phone = v.phone,
van_status = v.van_status
};
gcVans.DataSource = vans;
So, I have two questions:
1) If I cannot use computed properties of my partial classes in LINQ projections, how am I supposed to show my computed string in my datagrid?
2) Am I even approaching this correctly? When I resolve #1, how would I refresh this data (ie during a timer fire event)? Would I simply call objDB.refresh() and then tell my datagrid to update from the datasource? Does calling that method actually run the lambda expression above or does it load everything from the DB?
Thanks for any assistance with this. Also, if you have any best practices to share that would be awesome! I hope I explained this as thoroughly as you need to provide assistance.
1) Instead of modifying your EF object with a partial class you could always create your own class that contains your read only property van_status. The code you've got would be nearly identical:
Models.dataEntities objDB = new Models.dataEntities();
gcVans.DataSource = from v in objDB.vans
select new DisplayVan {
van_name = v.van_name,
school_name = v.school.school_name,
capacity = v.capacity,
phone = v.phone,
};
The van_status property, since it's read-only, will not need to be specified in the query.
2) I'm more a web developer than a desktop developer so I'll give you my take on how to refresh the grid (it may not be the preferred methodology for fat clients)...
I'm reluctant to trust .Refresh() methods and hope all works to maximal efficiency and work properly. Instead, encapsulate the code from #1 in a method of your own and invoke it from your timer event firing (or however you choose to implement the periodic refresh).
Another good option would be to create an extension method.
Here is a simple example:
using System;
namespace WindowsFormsApplication1 {
static class Program {
[STAThread]
static void Main() {
Van van = new Van();
string status = van.GetStatus();
}
}
public static class VanExtension {
public static string GetStatus(this Van van) {
if(van.is_offline == 1) {
return "Offline";
}
else if(van.is_prayer_room == 1) {
return "In Prayer Room";
}
return "TODO: Create statuses";
}
}
public class Van {
public int is_offline { get; set; }
public int is_prayer_room { get; set; }
}
}
Be sure to put this extension class in the same namespace as the entity class.
Related
In asp.net core 2.1 Identity I am using a class to move the login name from ExternalLogin.cshtml.cs and Login.cshtml to save them to another table via a class AddUserToStudentTable.
EDIT - I have got the terminology of DTO wrong, but consider it just a class that pushes data around. I just used the wrong naming convention.
The class is
public class StudentNameDTO : IStudentNameDTO
{
public string StudentGoogleNameLogin { get; set; } = string.Empty;
public bool IsExternal { get; set; } = false;
}
The Startup is using AddSingleton but I have also tried AddTransient, with no difference.
services.AddSingleton<IStudentNameDTO, StudentNameDTO>();
And I am using the usual Constructor injection automatically done with wonderful VS 2017
Yet when passing data I always get an error of
evaluation of method () calls into native method system System.Environment.FailFast().
and it all crashes down with
NullReferenceException: Object reference not set to an instance of an object.
ASPNZBat.Business.AddUserToStudentTable.AddUserToStudent(string Email) in AddUserToStudentTable.cs + if (_studentNameDTO.IsExternal == true) ASPNZBat.Areas.Identity.Pages.Account.ExternalLoginModel.OnGetCallbackAsync(string returnUrl, string remoteError) in ExternalLogin.cshtml.cs + _addUserToStudentTable.AddUserToStudent(Email);
I have tried using AddTransient and AddScope as well in the startup, but no difference. Having worked on it for hours I am starting to doubt my ability to program....
Note that when there is data passing through it works OK. But when there is no data - null - instead of working with it it just crashes. I even wrapped it in a boolean to see if I could catch the output with that but it crashed at the boolean as well.
Data going in
if (info.Principal.Identity.Name != null)
{
_studentNameDTO.IsExternal = true;
_studentNameDTO.StudentGoogleNameLogin = info.Principal.Identity.Name;
string Email = info.Principal.FindFirstValue(ClaimTypes.Email);
_addUserToStudentTable.AddUserToStudent(Email);
}
Data coming out
string StudentName = string.Empty;
if (_studentNameDTO.IsExternal == true)
{
StudentName = _studentNameDTO.StudentGoogleNameLogin;
}
There is something about passing null data that it doesn't like and I don't understand.
Here is the github acc for it https://github.com/Netchicken/ASPNZBatV2/tree/master/ASPNZBat
It looks like you've got a case of Over-Dependency Injection.
Aside: You almost certainly don't want to be using AddSingleton here, a singleton is something that you want your application to have no more than one instance of during its execution. In this instance that would mean that if you had two users logging (or whatever the process is here) in at the same time they would both share the same instance of StudentNameDTO.
Based on the code in AddUserToStudentTable.cs the reason you're seeing a NullReferenceException is that there's nothing here that assigns to _studentNameDTO prior to it being used. It's not being injected anywhere, nor is it being passed into the class anywhere, it's declared private so isn't accessible from outside the class and is only read from on lines 36 and 38.
That said, not everything in your code needs, or should, be instantiated via Dependency Injection. Your StudentNameDTO isn't something the class depends on, it's something it consumes / modifies. From a cursory look at your code, it looks like the place that obtains all the data that's stored into StudentNameDTO is in ExternalLoginModel.OnGetCallbackAsync so this is where you should var studentNameDto = new StudentNameDTO() before calling AddUserToStudent and passing the instance of StudentNameDTO into the method, e.g. (line 97 onwards):
if (info.Principal.Identity.Name != null)
{
var studentNameDto = new StudentNameDTO
{
IsExternal = true,
_studentNameDTO.StudentGoogleNameLogin = info.Principal.Identity.Name
};
string Email = info.Principal.FindFirstValue(ClaimTypes.Email);
_addUserToStudentTable.AddUserToStudent(studentNameDto, Email);
}
In my "LuaTest" namespace I have a class called "Planet". The C# code reads like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LuaInterface;
namespace LuaTest
{
public class Planet
{
public Planet(string name)
{
this.Name = name;
}
public Planet() : this("NoName") { }
public string Name
{
get;
private set;
}
public void printName()
{
Console.WriteLine("This planet's name is {0}", Name);
}
}
}
Then I built LuaTest.dll and copied this file to the same folder where my Lua script is saved. In the Lua script I wrote:
--define Path for required dlls
package.cpath = package.cpath .. ";" .. "/?.dll"
package.path = package.path .. ";" .. "/?.dll/"
require 'luanet'
luanet.load_assembly("LuaTest")
local Planet = luanet.import_type("LuaTest.Planet")
local planet = Planet("Earth")
planet.printName()
However, this piece of code does not work. Lua interpreter throws this error:
lua: dllTest.lua:7: attempt to call local 'Planet' (a nil value)
I suspect that my LuaTest assembly is not loaded at all. Could anyone point out where I did wrong? I would very much appreciate it, since I've been stuck by this problem for days.
Also it might be helpful to add that my LuaInterface.dll is the rebuilt version in .NET4.0 environment.
So I spent a LOT of time similarly. What really drove me bonkers was trying to get Enums working. Eventually I ditched my project for a very simplified console application, very similar (ironically also named 'LuaTest').
Edit: I've noted that the initial "luanet.load_assembly("LuaTest")" appears superfluous. Works with it, or surprisingly without it.
Another Edit: As in my badly edited comment below, when I removed:
print(luanet.LuaTest.Pointless)
It all stopped working (LuaTest.Pointless became nil). But adding the luanet.load_assembly("LuaTest") then makes it work. It may be that there is some sort of odd implicit load in the print or in just expressing they type. Very Strange(tm).
In any case, it seems to work for me (note: after a lot of experimentation). I don't know why yours is failing, I don't note any real difference, but here's all my code in case someone else can spot the critical difference:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LuaInterface;
namespace LuaTest
{
public class Program
{
static void Main(string[] args)
{
Lua lua = new Lua();
lua.DoFile("test.lua");
}
public int some_member = 3;
}
public class Pointless
{
public enum AnEnum
{
One,
Two,
Three
};
public static string aStaticInt = "This is static.";
public double i;
public string n = "Nice";
public AnEnum oneEnumVal = AnEnum.One;
private AnEnum twoEnumVal = AnEnum.Two;
private string very;
public Pointless(string HowPointLess)
{
i = 3.13;
very = HowPointLess;
}
public class MoreInnerClass
{
public string message = "More, please!";
}
public void Compare(AnEnum inputEnum)
{
if (inputEnum == AnEnum.Three)
Console.WriteLine("Match.");
else
Console.WriteLine("Fail match.");
}
}
}
and test.lua:
luanet.load_assembly("LuaTest")
--Pointless is a class in LuaTest assembly
local Pointless = luanet.import_type("LuaTest.Pointless")
print(Pointless)
--Gives 'ProxyType(LuaTest.Pointless): 46104728
print(Pointless.aStaticInt)
--'This is static.'
--Fails if not static, as we expect
--Instantiate a 'Pointless'.
local p = Pointless("Very")
print(p)
--Gives 'LuaTest.Pointless: 12289376'
--Now we can get at the items inside the Pointless
--class (well, this instance, anyway).
local e = p.AnEnum;
print(e)
--ProxyType(LuaTest.Pointless+AnEnum): 23452342
--I guess the + must designate that it is a type?
print(p.i)
--3.14
print(p.oneEnumVal)
--Gives 'One: 0'
print(p.twoEnumVal)
--Gives 'twoEnumVal'... private
--behaves very differently.
print(e.Two:ToString())
--Gives 'Two'
local more = p.MoreInnerClass()
print(more.message)
--'More, Please!'
--create an enum value here in the script,
--pass it back for a comparison to
--the enum.
local anotherEnumVal = p.AnEnum.Three
p:Compare(anotherEnumVal)
--outputs 'Match'
Having spent the last several days working on a project that required this exact functionality from LuaInterface, I stumbled across a piece of Lua code that turned out to be the perfect solution (see Reference 1). Whilst searching for this solution, I noticed this question and figured I'd drop my two cents in.
To apply this solution, I merely run the CLRPackage code while initializing my LuaInterface Lua object. However, the require statement works just as well.
The code provided in reference 1 allows the use of import statements, similar to C# using statements. Once an assembly is imported, its members are accessible in the global namespace. The import statement eliminates the need to use load_assembly or import_type (except in situations in which you need to use members of the same name from different assemblies. In this scenario, import_type would be used similar to C# using NewTypeName = Assembly.OldTypeName).
import "LuaTest"
planet = Planet("Earth")
planet:printName()
This package also works great with enums!
Further information regarding the use of this package may be found at Reference 2.
Hope this helps!
Reference 1: https://github.com/stevedonovan/MonoLuaInterface/blob/master/bin/lua/CLRPackage.lua
Reference 2: http://penlight.luaforge.net/project-pages/penlight/packages/LuaInterface/
I spent some time in binding C# dll to lua. Your posts were helpful but something was missing. The following solution should work:
(Make sure to change your compiler to .NET Framework 3.5 or lower!)
Planet.dll:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Planets
{
public class Planet
{
private string name;
public string Name
{
get { return name; }
set { this.name = value; }
}
private float diameter;
public float Diameter
{
get { return diameter; }
set { this.diameter = value; }
}
private int cntContinents;
public int CntContinents
{
get { return cntContinents; }
set { this.cntContinents = value; }
}
public Planet()
{
Console.WriteLine("Constructor 1");
this.name = "nameless";
this.diameter = 0;
this.cntContinents = 0;
}
public Planet(string n, float d, int k)
{
Console.WriteLine("Constructor 2");
this.name = n;
this.diameter = d;
this.cntContinents = k;
}
public void testMethod()
{
Console.WriteLine("This is a Test!");
}
}
}
Use the code above, paste it into your class library project and compile it with .NET smaller or equal 3.5.
The location of the generated DLL needs to be known by the lua enviroment. Paste it e.g at "clibs"-folder or another well known lua system path. Then try to use the following lua example. It should work.
Test1.lua: (Option 1 with "import" from CLRPackage)
require "luanet"
require "CLRPackage"
import "Planet"
local PlanetClass = luanet.import_type("Planets.Planet")
print(PlanetClass)
local PlanetObject1 = PlanetClass()
print(PlanetObject1)
local PlanetObject2 = PlanetClass("Earth",6371.00*2,7)
print(PlanetObject1.Name)
PlanetObject1.Name = 'Mars'
print(PlanetObject1.Name)
print( "Planet " ..
PlanetObject2.Name ..
" is my home planet. Its diameter is round about " ..
PlanetObject2.Diameter .. "km." ..
" Our neighour is " ..
PlanetObject1.Name)
Test2.lua: (Option 2 with "load_assembly")
require "luanet"
require "CLRPackage"
luanet.load_assembly("Planet")
local PlanetClass = luanet.import_type("Planets.Planet")
print(PlanetClass)
local PlanetObject1 = PlanetClass()
print(PlanetObject1)
local PlanetObject2 = PlanetClass("Earth",6371.00*2,7)
print(PlanetObject1.Name)
PlanetObject1.Name = 'Mars'
print(PlanetObject1.Name)
print( "Planet " ..
PlanetObject2.Name ..
" is my home planet. Its diameter is round about " ..
PlanetObject2.Diameter .. "km." ..
" Our neighour is " ..
PlanetObject1.Name)
In both cases the console output will look like this:
ProxyType(Planets.Planet): 18643596
Constructor 1
Planets.Planet: 33574638
Constructor 2
nameless
Mars
Planet Earth is my home planet. Its diameter is round about 12742km. Our neighbour is Mars
I hope its helps some of you.
Edit 1:
by the way, a method call from lua looks like this:
PlanetObject1:testMethod()
PlanetObject2:testMethod()
Edit 2:
I found different dll's whitch needed to be handled differently. One needed the "import"-function and another needed the "load_assembly"-function. Keep that maybe in mind!
I have a list consisting of all the US Zip codes, each with 3 elements. Thus the list is ~45,000 x 3 strings. What is the best way to load this, essentially the most efficient/optimized? Right now I have a foreach loop running it, and every time it gets to the loading point it hangs. Is there a better approach?
Edit
The usage of this is for the user to be able to type in a zip code and have the city and state displayed in two other text boxes. Right now I have it set to check as the user types, an after the dirt number is entered it freezes up, I believe at the ZipCodes codes = new ZipCodes()
This is the code I'm currently using. I left one of the zipCode.Add statements in, but deleted the other 44,999.
struct ZipCode
{
private String cvZipCode;
private String cvCity;
private String cvState;
public string ZipCodeID { get { return cvZipCode; } }
public string City { get { return cvCity; } }
public string State { get { return cvState; } }
public ZipCode(string zipCode, string city, string state)
{
cvZipCode = zipCode;
cvCity = city;
cvState = state;
}
public override string ToString()
{
return City.ToString() + ", " + State.ToString();
}
}
class ZipCodes
{
private List<ZipCode> zipCodes = new List<ZipCode>();
public ZipCodes()
{
zipCodes.Add(new ZipCode("97475","SPRINGFIELD","OR"));
}
public IEnumerable<ZipCode> GetLocation()
{
return zipCodes;
}
public IEnumerable<ZipCode> GetLocationZipCode(string zipCode)
{
return zipCodes;
}
public IEnumerable<ZipCode> GetLocationCities(string city)
{
return zipCodes;
}
public IEnumerable<ZipCode> GetLocationStates(string state)
{
return zipCodes;
}
}
private void LocateZipCode(TextBox source, TextBox destination, TextBox destination2 = null)
{
ZipCodes zips = new ZipCodes();
string tempZipCode;
List<ZipCode> zipCodes = new List<ZipCode>();
try
{
if (source.Text.Length == 5)
{
tempZipCode = source.Text.Substring(0, 5);
dataWorker.RunWorkerAsync();
destination.Text = zipCodes.Find(searchZipCode => searchZipCode.ZipCodeID == tempZipCode).City.ToString();
if (destination2.Text != null)
{
destination2.Text = zipCodes.Find(searchZipCode => searchZipCode.ZipCodeID == tempZipCode).State.ToString();
}
}
else destination2.Text = "";
}
catch (NullReferenceException)
{
destination.Text = "Invalid Zip Code";
if (destination2 != null)
{
destination2.Text = "";
}
}
}
There are several options that depend on your use case and target client machines.
Use paged controls. Use existing paged control variants (eg. telerik) which support paging. This way you will deal with smaller subset of the data available.
Use search/filter controls. Force users to enter partial data to reduce the size of the data you need to show.
Using observable collection will cause performance problems as framework provided class does not support bulk load. Make your own observable collection which supports bulk loading (which does not raise collection changed event on every element you add). On a list of 5-10.000 members I've seen loading times reduced from 3s to 0.03s.
Use async operations when loading data from db. This way UI stays responsive and you have a chance to inform users about the current operation. This improves the perceived performance immensely.
Instead of loading all of the items, try loading on demand. For instance, when user enters the first three letters then query the list and return only matching items. Many controls exists for this purpose both in silverlight and ajax.
Thanks for all the responses, I really do appreciate them. A couple I didn't really understand, but I know that's my own lack of knowledge in certain areas of c#. In researching them though, I did stumble across a different solution that had worked beautifully, using a Dictionary<T> instead of a List. Even without using a BackgroundWorker, it loads on app start-up in about 5 seconds. I had heard of Dictionary<T> before, but until now had never had a cause to use/research it, so this was doubly beneficial to me. Thanks again for all the assistance!
I have a three polymorphed classes. Based on user input the class should be set to that user's input. So the child class is decided by a user, and should make for 'class = new inputClass'. The snippet of code looks like:
public void characterGeneration(string classSelected)
{
foreach (string classInList in classes.ClassList)
{
if (classSelected == classInList)
{
PlayerOneStats = new Mage();
}
}
PlayerOneStats.generateStats();
}
Where it says PlayerOneStats = new Mage();, I want the Mage() to be the user input.
I've looked at Activator, Assembly, using Type, trying to cast over to the parent of GenerateStats, but nothing works. I've found many people saying it works, and one link that says it doesn't work. Can somebody please clear this up for me? Thank you very much!
Are you sure Activator doesn't work? Activator.CreateInstace("assembly-name", "type-name") seems like exactly what you want. What doesn't work?
What is the base class of Mage (and the other classes a user can select)? You should be able to do this:
public void characterGeneration(string classSelected)
{
foreach (string classInList in classes.ClassList)
{
if (classSelected == classInList)
{
PlayerOneStats = (GenerateStats)Assembly.GetExecutingAssembly().CreateInstance("YourNamespace." + classSelected);
break;
}
}
PlayerOneStats.generateStats();
}
Make sure that you include the namespace the type you want is contained in and this should work for you:
string classSelected = "testCode.Mage";
var player = Activator.CreateInstance(Type.GetType(classSelected));
Since Activator.CreateInstance() returns an object you will have to cast - in your case it would make sense to cast to an interface that all your player classes implement:
var player = (IPlayerCharacter) Activator.CreateInstance(Type.GetType(classSelected));
I have a MVC Web Application using the following approach:
public class MyController : Controller
{
public FooRepository fooRepository = new FooRepository();
public BarRepository barRepository = new BarRepository();
public ActionResult UpdateItems(int id, int range1, int range2)
{
Foo foo = fooRepository.GetItem(id);
List<Bar> bars = barRepository.GetItemsByRange(range1, range2);
// Some validation rules here...
DoSomeWork(foo, bars);
// Show confirmation / error message
}
private void DoSomeWork(Foo foo, List<Bar> bars)
{
foreach(int i = 0; i < bars.Count; i++)
{
bars[i].Prop1 = foo.Prop1; // This field is updated
bars[i].Owner = "someuser"; // This one too
bars[i].Status = BarStatus.SomeStatus; // This isn't...
}
foo.Status = FooStatus.SomeStatus; // Ok
// Calls DataContext.SubmitChanges()
fooRepository.SubmitChanges();
barRepository.SubmitChanges();
}
}
However, in some "random" cases (I see no pattern), one of the fields doesn't get updated, as noted in the comments.
It seems like LINQ isn't recognizing the field's update, so it gets excluded from the generated query.
Can anyone tell me if I'm missing something here, what could be causing it and/or how can I solve it?
Note: I don't get any Exception and can't verify this case in a development scenario.
From my experience if the error is random and you can't reproduce in development than the problem is user error.
Programming would be really hard if the .net framework or the CLR just randomly decided to do things differently.
You probably have an implicit/explicit bind exclusion floating around somewhere
[Bind(Exclude="...,Status,...")]
Just guessing of course
If Linq thinks that the Status is already BarStatus.SomeStatus, then it won't update it.
What can happen is that you find a record with the status set to this value, and then some other routine changes it, and then, if you are using your same DataContext, you will get the old value from the cached copy and hence Linq thinks that it does not need to update it.