Linq to SQL - Attribute based mapping - cannot instantiate new object with no arguments - sql

I want to extend Linq's DataContext class to implement the ORM. Currently my model looks like this:
public class Trial : DataContext
{
public Trial(string connectionString) : base(connectionString) { }
[Column(DbType = "System.Guid", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]
public Guid TrialID { get; set; }
//...
}
However when I try to instantiate a new Trial object to insert it into the database I get an error complaining that Trial does not have a constructor that takes 0 arguments. When I try to create such a constructor, VS complains that DataContext does not have a constructor that takes 0 arguments.
Am I missing something here? How do I seperate the data context from the model definition?
(First time using Linq!)
Thanks in advance,
Max.

Your data context that represents the database view should inherit from DataContext. It should expose Tables where T is the entities (rows) that you want to add. Try generating a model from the database using the designer or SQLMetal and take a closer look at the generated code to see what's going on.

Related

Deserializing IEnumerable with private backing field in RavenDb

I've been modeling a domain for a couple of days now and not been thinking at all at persistance but instead focusing on domain logic. Now I'm ready to persist my domain objects, some of which contains IEnumerable of child entities. Using RavenDb, the persistance is 'easy', but when loading my objects back again, all of the IEnumerables are empty.
I've realized this is because they don't have any property setters at all, but instead uses a list as a backing field. The user of the domain aggregate root can add child entities through a public method and not directly on the collection.
private readonly List<VeryImportantPart> _veryImportantParts;
public IEnumerable<VeryImportantPart> VeryImportantParts { get { return _veryImportantParts; } }
And the method for adding, nothing fancy...
public void AddVeryImportantPart(VeryImportantPart part)
{
// some logic...
_veryImportantParts.Add(part);
}
I can fix this by adding a private/protected setter on all my IEnumerables with backing fields but it looks... well... not super sexy.
private List<VeryImportantPart> _veryImportantParts;
public IEnumerable<VeryImportantPart> VeryImportantParts
{
get { return _veryImportantParts; }
protected set { _veryImportantParts = value.ToList(); }
}
Now the RavenDb json serializer will populate my objects on load again, but I'm curious if there isn't a cleaner way of doing this?
I've been fiddeling with the JsonContractResolver but haven't found a solution yet...
I think I've found the root cause of this issue and it's probably due to the fact that many of my entities were created using:
protected MyClass(Guid id, string name, string description) : this()
{ .... }
public static MyClass Create(string name, string description)
{
return new MyClass(Guid.NewGuid(), name, description);
}
When deserializing, RavenDb/Json.net couldn't rebuild my entities in a proper way...
Changing to using a public constructor made all the difference.
Do you need to keep a private backing field? Often an automatic property will do.
public IList<VeryImportantPart> VeryImportantParts { get; protected set; }
When doing so, you may want to initialize your list in the constructor:
VeryImportantParts = new List<VeryImportantPart>();
This is optional, of course, but it allows you to create a new class and start adding to the list right away, before it is persisted. When Raven deserializes a class, it will use the setter to overwrite the default blank list, so this just helps with the first store.
You certainly won't be able to use a readonly field, as it couldn't be replaced during deserialization. It might be possible to write a contract resolver or converter that fills an existing list rather than creating a new one, but that seems like a rather complex solution.
Using an automatic property can add clarity to your code anyway - as it is less confusing whether to use the field or the property.

WCF, Linq Error:cannot implicitly convert type System.linq.iorderedQueryable<> to System.Collection.Generic.List<>

I am getting an error : i am using entity framework, wcf.
Error:cannot implicitly convert type System.linq.iorderedQueryable<xDataModel.Info> to System.Collection.Generic.List<xServiceLibrary.Info>
Below are my code:
WCF Service:
namespace xServiceLibrary
{
public List<Info> GetScenario()
{
xEntities db = new xEntities();
var query = from qinfo in db.Infoes
select qinfo;
//return query.Cast<Info>().ToList(); (not working)
//return query.toList(); (not working)
return query;
}
}
Interface:
namespace xServiceLibrary
{
[OperationContract]
List<Info> GetScenario();
}
Class:
namespace xServiceLibrary
{
[DataContract]
public class Info
{
[DataMember]
public int Scenario_Id;
[DataMember]
public string Scenario_Name { get; set; }
[DataMember]
public string Company_Name { get; set; }
}
}
update:(2)
I have two class library files.
One is xDataModel namespace in which i have created xmodel.edmx file.
second is xServiceLibrary namespace where i am implementing Wcf Service.
i have attached the xDataModel.dll file in my xServiceLibrary so that i could query my EF Model.
i am not able to understand the concept. any help would be appreciated.
The problem is that you have two different types named Info: DataModel.Info and ServiceLibrary.Info - because these are different types you cannot cast one into the other.
If there is no strong reason for both being there I would eliminate one of them. Otherwise as a workaround you could project DataModel.Info to ServiceLibrary.Info by copying the relevant properties one by one:
var results = (from qinfo in db.Infoes
select new ServiceLibrary.Info()
{
Scenario_Id = qinfo.Scenario_Id,
//and so on
}).ToList();
The problem is that you have two different classes, both called Info, both in scope at the time you run your query. This is a very very bad thing, especially if you thought they were the same class.
If DataModel.Info and ServiceLibrary.Info are the same class, you need to figure out why they are both in scope at the same time and fix that.
If they are different classes, you need to be explicit about which one you are trying to return. Assuming that your EF model includes a set of DataModel.Info objects, your options there are:
Return a List<DataModel.Info> which you can get by calling query.ToList()
Return a List<ServiceLibrary.Info> which you can get by copying the fields from your DataModel.Info objects:
var query = from qinfo in db.Info
select new ServiceLibrary.Info
{
Scenario_Id = q.Scenario_Id,
Scenario_Name = q.Scenario_Name
Company_Name = q.Company_Name
};
Return something else, such as your custom DTO object, similar to #2 but with only the specific fields you need (e.g. if ServiceLibrary.Info is a heavy object you don't want to pass around.
In general, though, your problem is centered around the fact that the compiler is interpreting List<Info> as List<ServiceLibrary.Info> and you probably don't want it to.

NHibernate query by Transient instance results in "save the transient instance"-exception

I have some old code which is performing a query where a model can be transient. That is, a model with some fields populated from user input, which are then used as part of the query.
It worked under NH 2.1.x, but is failing under the latest version.
The exception raised is "object references an unsaved transient instance - save the transient instance before flushing". This happens when NH attempts to perform a query using a non-persisted object as part of the query.
A simplified version to illustrate the problem.
abstract class BaseModel
public virtual long Id { get; set; }
class Car : BaseModel
public virtual Engine Engine { get;set; }
class Engine : BaseModel
public virtual string Kind { get; set; }
public static IList<Car> GetByEngine(Engine eng) {
ICriteria c = Session.CreateCriteria<Car>();
c.Add(Expression.Eq("Engine", eng));
return c.List<Car>(); // <--- Error occurs here
}
And calling code is equivalent to this:
Engine obj = new Engine { Id = 42 }; // Transient instance
var x = GetByEngine(obj);
What I expected to happen (Which appears to be the behaviour of the old NHibernate version), is that the Engine passed is used only for getting the Id. That is, generating SQl like
select .... from Cars where Engine = 42
But with the new version NHibernate seems to check that the engine used in the Expression is actually persisted.
Is there a way to avoid having to load a persisted Engine before performing the query ?
yes using Session.Load() which returns the object if already in the session or a lazyLoadingProxy if not present.
public static IList<Car> GetByEngine(Engine eng) {
ICriteria c = Session.CreateCriteria<Car>();
c.Add(Expression.Eq("Engine", Session.Load<Engine>(eng.Id)));
return c.List<Car>();
}
You can use the Session.Load method, which exist for this kind of scenarios.
The Load method will return a Proxy to the Entity and won't hit the Data Base untill you access one of it's properties, (except the Primary key property which won't hit the DB at all).
Usage:
Engine obj = session.Load<Engine>(42);
var x = GetByEngine(obj);
check this article about Session.Get and Session.Load
I think you could do something like this:
public static IList<Car> GetByEngine(Engine eng) {
ICriteria c = Session.CreateCriteria<Car>().CreateCriteria("Engine");
c.Add(Expression.Eq("Id", eng.Id));
return c.List<Car>();
}
Anyway... how it's possible that a car with that engine exists if you haven't saved it yet?

Setting the DataContext on an Entity instance after it's retrieved

I'm trying to find a way to have the DataContext available from within Entities.
I want to do something like this:
partial public class MyEntity
public DataContext as MyDataContext
private sub OnLoaded()
Me.DataContext = <the context that retrieved this instance>
end sub
end class
First, can something like this be done?
Second, assuming that I'm not going to use this entity with any other DataContext, is there any dangers or gotchas in doing such a thing?
This is the way I do it currently:
partial public class MyDataContext
public function GetMyEntity(byval id as integer) as MyEntity
dim o = MyEntities.SingleOrDefault(function(e) e.id = id)
if o isnot nothing then o.DataContext = Me
return o
end function
end class
Although you didn't specify a real reason for it, just a sidenote from MSDN:
In general, a DataContext instance is
designed to last for one "unit of
work" however your application defines
that term. A DataContext is
lightweight and is not expensive to
create. A typical LINQ to SQL
application creates DataContext
instances at method scope or as a
member of short-lived classes that
represent a logical set of related
database operations.
and one more:
Do not try to reuse instances of
DataContext. Each DataContext
maintains state (including an identity
cache) for one particular edit/query
session. To obtain new instances based
on the current state of the database,
use a new DataContext.
and finally,
... Any instance members are not
guaranteed to be thread safe.
But still in some cases semi-persistent solutions could be very helpful. Take a look onto Rick Strachl's article: Linq to SQL DataContext Lifetime Management. There are different approaches of DataContext management is reviewed in it. On of them - Create a per business object DataContext is exactly what you need.
You could use a singleton pattern on the DataContext, but you will need some kind of lifetime management on it, as it is not good to keep it around to long. (request ends dispose it maybe)
Example in C#, but I hope you can understand it.
public class MyDataContext
{
public static MyDataContext Current
{
get
{
MyDataContext context = (MyDataContext)HttpContext.Current.Items["Context"];
if(context == null)
{
context = new MyDataContext();
HttpContext.Current.Items["Context"] = context;
}
return context;
}
}
}
public class MyEntity
{
public MyDataContext DataContext
{
get{ return MyDataContext.Current;}
}
}
In Global.asax you can hook up the event Application_EndRequest and call MyDataContext.Current.Dispose(); to dispose of the context manually instead of waiting for the GC to do it.

How do I convert an object from Reflection to a generic collection?

I'm trying to write a Compare method to compare properties in some POCOs using Reflection to ensure that they've been persisted to the database correctly. For example, let's say I have this POCO:
public class NoahsArk
{
public string Owner { get; set; }
public ICollection<Animal> Animals { get; set; }
}
What I want to do is this:
[Test]
public class Saves_Correctly_To_Database()
{
var noahsArk = new NoahsArk { // some setup code here };
db.Save(noahsArk);
var dbNoahsArk = db.Get<NoahsArk>(noahsArk.Id);
Assert.That(Compare(noahsArk, dbNoahsArk), Is.True);
}
The ORM I'm using is NHibernate. My Compare method looks like this so far:
public static bool EqualsProperties<T>(this T x, T y)
{
var xType = x.GetType();
foreach (var property in xType.GetProperties())
{
if (property.GetValue(x, null).Implements(typeof(ICollection<>)))
{
var xValue = property.GetValue(x, null) as ICollection<T>;
var yValue = property.GetValue(y, null) as ICollection<T>;
}
Object.Implements() is an extension method I wrote to determine if a type implements an interface. As you can see, the method is incomplete. The problem I'm running into is that when I use property.GetValue(x, null), it returns an object, and I don't know how to cast it into its specific generic ICollection type. I need to be able to do this so I can use LINQ to do a x.Contains(y) to compare the two collections for equality. Any idea on how to do this?
P.S. I tried using Compare .NET Objects, but it's giving me a null reference exception somewhere deep within NHibernate. It doesn't properly handle how NHibernate proxies the ICollection for lazy loading. To make matters worse, NHibernate modifies the POCO to support lazy-loading, but this is all done at runtime. In the source code, it looks like you're just working with a regular ICollection, but NHibernate changes this to NHibernate.Collections.Generic.PersistentSet at runtime, and this is what's causing the comparer to fail.
Your question is a bit confusing because you don't need the type parameter T in the declaration of your EqualsProperties method. You just need
public static bool EqualsProperties(this object x, object y)
You then go on to use the same parameter T to cast properties of x and y to ICollection<T>; however, the objects in these collections obviously may have a different type than x and y.
Now to answer your question: you don't need to cast to the correct generic type to use the LINQ Contains method. You can do something like this:
xValue = property.GetValue(x, null);
yValue = property.GetValue(y, null);
if (typeof(IEnumerable).IsInstanceOf(x))
{
IEnumerable<object> xEnumerable = (x as IEnumerable).Cast<object>();
IEnumerable<object> yEnumerable = (y as IEnumerable).Cast<object>();
// use any LINQ method you like now
}
You should also make sure you use the LINQ overloads that take an equality comparer, as your domain objects obviously do not override the Equals method themselves. Otherwise you wouldn't be writing this unit testing code to compare them.
Sharp architecture framework use attribute to decor properties which should be taken into the equals method. See the source code of DomainSignatureAttribute class and EntityWithTypedId<>.Equals method.