How to update two columns with same name from two tables in a join query - sql

I am getting an error:
Property or Indexer cannot be assigned to "--" it is read only
when trying to update two columns with the same name in two tables in a join query. How do I get this to work? Thanks!

The anonymous object created in your projection ("select new" part) is read-only and its properties are not tracked by data context by any means.
Instead, you can try this:
//...
select new
{
p1 = p,
p2 = t
}
foreach (var row in updates)
{
row.p1.Processed = true;
row.p2.Processed = true;
}
In order to improve performance you may also want to take a look at batch update capabilities of Entity Framework Extensions (if you are using Entity Framework): https://entityframework-extensions.net/overview

Yes, that's due to anonymous type properties are read only, from documentation:
Anonymous types provide a convenient way to encapsulate a set of
read-only properties into a single object without having to explicitly
define a type first.
I suggest you to create a custom class with the two entities you need (a DTO):
public class PassengerDTO
{
public Passenger Passenger {get;set}
public PassengerItinerary PassengerItinerary {get;set}
}
And use it in your projection, You need the entity instances and not just the properties you want to modify because, when you modify the Processed property in the foreach the proxy class that represent your entity is going to change the status of you entity to Updated.

Related

Does CF ORM have an Active Record type Update()?

Currently I am working partly with cfwheels and its Active Record ORM (which is great), and partly raw cfml with its Hibernate ORM (which is also great).
Both work well for applicable situations, but the thing I do miss most when using CF ORM is the model.update() method that is available in cfwheels, where you can just pass a form struct to the method, and it will map up the struct elements with the model properties and update the records.. really good for updating and maintaining large tables. In CF ORM, it seems the only way to to update a record is to set each column individually, then do a save. Is this the case?
Does cf9 ORM have an Active Record type update() (or equivalent) method which can just receive a struct with values to update and update the object without having to specify each one?
For example, instead of current:
member = entityLoadByPK('member',arguments.id);
member.setName(arguments.name);
member.setEmail(arguments.email);
is there a way to do something like this in CF ORM?
member = entityLoadByPK('member',arguments.id);
member.update(arguments);
Many thanks in advance
In my apps I usually create two helper functions for models which handle the task:
/*
* Get properties as key-value structure
* #limit Limit output to listed properties
*/
public struct function getMemento(string limit = "") {
local.props = {};
for (local.key in variables) {
if (isSimpleValue(variables[local.key]) AND (arguments.limit EQ "" OR ListFind(arguments.limit, local.key))) {
local.props[local.key] = variables[local.key];
}
}
return local.props;
}
/*
* Populate the model with given properties collection
* #props Properties collection
*/
public void function setMemento(required struct props) {
for (local.key in arguments.props) {
variables[local.key] = arguments.props[local.key];
}
}
For better security of setMemento it is possible to check existence of local.key in variables scope, but this will skip nullable properties.
So you can make myObject.setMemento(dataAsStruct); and then save it.
There's not a method exactly like the one you want, but EntityNew() does take an optional struct as a second argument, which will set the object's properties, although depending on how your code currently works, it may be clunky to use this method and I don;t know whether it'll have any bearing on whether a create/update is executed when you flush the ORM session.
If your ORM entities inherit form a master CFC, then you could add a method there. Alternatively, you could write one as a function and mix it into your objects.
I'm sure you're aware, but that update() feature can be a source of security problems (known as the mass assignment problem) if used with unsanitized user input (such as the raw FORM scope).

Keeping NHibernate from loading some fields

This is a follow on question to My earlier question on lazy loading properties. Since the application is an enhancement to a production application in a fairly major enterprise, and it currently running using NHib 1.2, upgrading to version 3 is not going to happen, so the suggested answer of using Lazy Properties in 3.0 won't work for me.
To summarize the problem, I have simple database with 2 tables. One has about a dozen simple fields, plus a one to many relation to the second table as a child table. Two of the fields are very large blobs (several megabytes each), and I want to, effectively, lazy load them. This table has about 10 records, and they populate a grid at start up, but access to the large blobs are only needed for whatever row is selected.
The object structure looks something like this:
[Serializable]
[Class(Schema = "dbo", Lazy = false)]
public class DataObject
{
[Id(-2, Name = "Identity", Column="Id")]
[Generator(-1, Class="native")]
public virtual long Identity { get; set;}
[Property]
public string FieldA { get; set;}
[Property]
public byte[] LongBlob {get; set;}
[Property]
public string VeryLongString { get; set;}
[Bag(-2, Cascade=CascadeStyle.All, Lazy= false, Inverse=true)]
[Key(-1, Column="ParentId")]
[OneToMany(0, ClassType=typeof(DataObjectChild))]
public IList<DataObjectChild> ChildObjects { get; set;}
}
Currently, the table is accessed with a simple query:
objectList = (List<DataObject>) Session.CreateQuery("from DataObject").List<DataObject>();
And that takes care of everything, including loading the child objects.
What I would like is a query to do exactly the same thing, except select a list of the properties of the DataObject that includes everything EXCEPT the two blobs. Then I can add custom property Getters that will go out and load those properties when they are accessed.
So far, I have not been successful at doing that.
Things I have tried:
a) constructing an HQL query using a SELECT list.
It looks something like this:
objectList = (List<DataObject>) Session.CreateQuery(
"SELECT new DataObject " +
"(obj.Identity, obj.FieldA) " +
"from DataObject as obj")
That works, though I have to add a constructor to the DataObject that will construct it from fields I select, which is rather cumbersome. But then it doesn't load and expand the list of child objects, and I can't figure out how to do that easily (and don't really want to - I want to tell NHib to do it.)
b) removing the [Property] attribute from the two fields in the object definition. That keeps the NHibernate.Mapping.Attributes from mapping those fields, so they don't get included in the query, but then I have no way to access them from NHib at all, including writing them out when I go to save a new or modified DataObject.
I'm thinking there has to be an easier way. Can somebody point me in the right direction?
Thanks
I think you're on the right path. However, you're going to have to do more manual work since you're using a very old version of NHibernate. I would fetch projections of your entities that contain only the columns you want to eagerly load. Then when the UI requests the large blob objects, you're going to have to write another query to get them and supply them to the UI.
Another option would be to have a second class (e.g. SmallDataObject) with the same mapping (but without the blobs) and use that for the list. When editing a list item you would load the class with the blobs using the id of the selected list item.
In any case, modifying the mapping after the creation of the SessionFactory is not possible, so you cannot get rid of the mapped properties on demand.

NHibernate convert subclass to parent class

Supposing the following entities :
public class AppUser
{
public virtual int Id { get; set; }
public virtual string Login { get; set; }
}
// Mapped as joined-subclass
public class Person : AppUser
{
public virtual int Age { get; set; }
}
If I create 1 AppUser, and save it like this
var user = new AppUser() { Login = "test" };
session.Save( user ); // let's say Id = 1
How can I cast/convert/"promote" it to a Person, keeping the same ID ?
Now, i'm stuck with a row in my AppUser table, with Id = N. How can I populate the Person table with the same Id ? I can't delete the AppUser and recreate it as a Person, as AppUser may be referenced by foreign keys.
I could issue a "manual" SQL INSERT, but it's kind of ugly...
This is definitively a NHibernate question. I understand that from an OOP point of view, this makes little sense, hence the absence of other tags than nhibernate.
I don't believe nHibernate is going to be able to solve this problem for you. nHibernate is dealing with your data as an object and, especially with joined-subclass I don't believe there is anything built in that allows you to change the subclass type on the fly, or at least change the type and retain the original ID.
I think your best bet is to write a stored procedure that, given an ID and a NEW type, removes all entries from subclass tables and adds a new entry to the correct subclass table.
Once that proc runs, then reload the object in nHibernate (and make sure you have thrown away any cached data relating to it), it should now be of the correct type you want to work with, set its NEW properties and save it.
That way you have a relatively generic stored proc that just changes your subclass types, but you dont need to add all the crazy logic to handle various properties on your subclasses.
This has been discussed on SO before and I am quoting Jon Skeet for posterity:
No. A reference to a derived class
must actually refer to an instance of
the derived class (or null). Otherwise
how would you expect it to behave?
For example:
object o = new object();
string s = (string) o;
int i = s.Length; // What can this sensibly do?
If you want to be able to convert an
instance of the base type to the
derived type, I suggest you write a
method to create an appropriate
derived type instance. Or look at your
inheritance tree again and try to
redesign so that you don't need to do
this in the first place.
In Skeet's example, string's are objects and objects are not strings. So the "upcasting" would not work.

Find Underlying Column Size Via NHibernate Metadata

Is there a way to use SessionFactory.GetClassMetadata(), or any other method you're aware of, to dynamically get the maximum size of a varchar column that underlies an NHibernate class' string property?
To clarify, I'm not looking to read a length attribute that's specified in the NHibernate mapping file. I want to deduce the actual database column length.
See the code below for two different ways you can get the column size for a string from NHib metadata.
Cheers,
Berryl
[Test]
public void StringLength_DefaultIs_50_v1()
{
_metadata = _SessionFactory.GetClassMetadata(typeof(User));
var propertyType = _metadata.GetPropertyType("Email") as StringType;
Assert.That(propertyType.SqlType.Length, Is.EqualTo(50));
}
[Test]
public void StringLength_DefaultIs_50_v2()
{
var mapping = _Cfg.GetClassMapping(typeof(User));
var col = mapping.Table.GetColumn(new Column("Email"));
Assert.That(col.Length, Is.EqualTo(50));
}
When the Session factory is generated the NH engine does not check (and retrieve) what the underlying database is. For your case either you provide a "rich" mapping to have everything available at runtime, OR make a function that reads the necessary information from the DB (ie select * from sys.columns ..... for sql-server) when you need it.
Mind you that a rich mapping also allows the NH engine to make some automations (like checking if the size of the string passed is larger than the length of the (n)varchar column)

Serialize Entity Framework objects into JSON

It seems that serializing Entity Framework objects into JSON is not possible using either WCF's native DataContractJsonSerializer or ASP.NET's native JavaScript serializer. This is due to the reference counting issues both serializers reject. I have also tried Json.NET, which also fails specifically on a Reference Counting issue.
Edit: Json.NET can now serialize and deserialize Entity Framework entities.
My objects are Entity Framework objects, which are overloaded to perform additional business functionality (eg. authentication, etc.) and I do not want to decorate these classes with platform-specific attributes, etc. as I want to present a platform-agnostic API.
I've actually blogged about the individual steps I went though at https://blog.programx.co.uk/2009/03/18/wcf-json-serialization-woes-and-a-solution/
Have I missed something obvious?
The way I do this is by projecting the data I want to serialize into an anonymous type and serializing that. This ensures that only the information I actually want in the JSON is serialized, and I don't inadvertently serialize something further down the object graph. It looks like this:
var records = from entity in context.Entities
select new
{
Prop1 = entity.Prop1,
Prop2 = entity.Prop2,
ChildProp = entity.Child.Prop
}
return Json(records);
I find anonymous types just about ideal for this. The JSON, obviously, doesn't care what type was used to produce it. And anonymous types give you complete flexibility as to what properties and structure you put into the JSON.
Microsoft made an error in the way they made EF objects into data contracts. They included the base classes, and the back links.
Your best bet will be to create equivalent Data Transfer Object classes for each of the entities you want to return. These would include only the data, not the behavior, and not the EF-specific parts of an entity. You would also create methods to translate to and from your DTO classes.
Your services would then return the Data Transfer Objects.
Based off of #Craig Stuntz answer and similar to a DTO, for my solution I have created a partial class of the model (in a separate file) and a return object method with how I want it using only the properties that will be needed.
namespace TestApplication.Models
{
public partial class Employee
{
public object ToObject()
{
return new
{
EmployeeID = EmployeeID,
Name = Name,
Username = Username,
Office = Office,
PhoneNumber = PhoneNumber,
EmailAddress = EmailAddress,
Title = Title,
Department = Department,
Manager = Manager
};
}
}
}
And then I call it simply in my return:
var employee = dbCtx.Employees.Where(x => x.Name == usersName).Single();
return employee.ToObject();
I think the accepted answer is more quick and easy, I just use my method to keep all of my returns consistent and DRY.
My solution was to simply remove the parent reference on my child entities.
So in my model, I selected the relationship and changed the Parent reference to be Internal rather than Public.
May not be an ideal solution for all, but worked for me.
One more solution if you want to have better code consistency is to use JavaScriptConverter which will handle circular reference dependencies and will not serialize such references.
I've blogged about here:
http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/
FYI I found an alternative solution
You can set the parent relationship as private so then the properties are not exposed during the translation removing the infinite property loop
I battled with this problem for days,
Solution. Inside your edmx window.
- right click and add code generation item
- Select Code tab
- select EF 4x.POCOC Entity Generator
If you don't see it, then you will have to install it with nuget, search EF.
The Entity generator will generate all you complex type and entity object into simple classes to serialize into json.
I solved it by getting only object types from System namespace, and then convert them to Dictionary and then add them to list. Works good for me :)
It looks complicated, but this was the only generic solution that worked for me...
I'm using this logic for a helper I'm making, so it's for a special use where I need to be able to intercept every object type in entity object, maybe someone could adapt it to his use.
List<Dictionary<string, string>> outputData = new List<Dictionary<string, string>>();
// convert all items to objects
var data = Data.ToArray().Cast<object>().ToArray();
// get info about objects; and get only those we need
// this will remove circular references and other stuff we don't need
PropertyInfo[] objInfos = data[0].GetType().GetProperties();
foreach (PropertyInfo info in objInfos) {
switch (info.PropertyType.Namespace)
{
// all types that are in "System" namespace should be OK
case "System":
propeties.Add(info.Name);
break;
}
}
Dictionary<string, string> rowsData = null;
foreach (object obj in data) {
rowsData = new Dictionary<string, string>();
Type objType = obj.GetType();
foreach (string propertyName in propeties)
{
//if You don't need to intercept every object type You could just call .ToString(), and remove other code
PropertyInfo info = objType.GetProperty(propertyName);
switch(info.PropertyType.FullName)
{
case "System.String":
var colData = info.GetValue(obj, null);
rowsData.Add(propertyName, colData != null ? colData.ToString() : String.Empty);
break;
//here You can add more variable types if you need so (like int and so on...)
}
}
outputData .Add(rowsData); // add a new row
}
"outputData " is safe for JSON encode...
Hope someone will find this solution helpful. It was fun writing it :)