Initializing Nested strongly typed objects in LINQ to Entities - c#-4.0

Consider this Example
public class FooWrapper
{
public FooWrapper() { }
public Foo FooObject { get; set; }
public Bar BarObject { get; set; }
}
public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
{
IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
IEnumerable<FooWrapper> results = (
from f in _entities.FooSet
join b in tempBar on f.ID equals b.foos.ID
select new FooWrapper
{
FooObject = f,
BarObject = b
});
return results;
}
what if my Foo type class has Properties like
public class Foo(){
FProperty1{get; set;}
FPorperty2{get; set;}
}
public class Bar(){
BProperty1{get; set;}
BProperty2{get; set;}
}
and now i want to initialize my object in query like this
select new FooWrapper
{
FooObject.FProperty1 = f,
BarObject.BProperty2 = b
});
can I do this?
How will this work?

What you want is:
select new FooWrapper
{
FooObject = new Foo { FProperty1 = f },
BarObject = new Bar { BProperty2 = b }
});

Related

Object creation from list <Class>

I want to create a new instance of a object which is holding a list object of another class.
public Class A
{
int a { get; set; };
List<B> b { get; set; }
}
public Class B
{
int c { get; set; };
}
public Class Test
{
A a= new A();
a.b= ? how to initiate this
a.b.c=some value;
}
I am not getting this value c here.how to get This value.
Try it this way:
public Class A
{
public int a { get; set; };
public List<B> b { get; set; }
public A()
{
b = new List<B>();
}
}
public Class B
{
public int c { get; set; };
}
public Class Test
{
A a= new A();
a.b= ? how to initiate this
a.b.Add(new B(){c = 13};
}
1.Try this initializing method
A objA = new A();
objA.a = 10;
objA.b = new List<B> { new B { C = 20 }, new B { C = 40 }, new B { C = 50 }, new B { C = 60 } };
2.Or try this one
A objA = new A();
objA.a = 10;
List<B> bList = new List<B>();
bList.Add(new B { C = 20 });
bList.Add(new B { C = 40 });
bList.Add(new B { C = 50 });
bList.Add(new B {C=60});
objA.b = bList;
And modify access specifiers of properties.

ServiceStack Ormlite Join Wrapper

I've created a wrapper in my data access for joins in OrmLite.
I'm now getting the exception:
System.Exception : Expression should have only one column
All of my entities have a base class of BaseEntity.
JoinType is just a facade to contain the column, selection and where of a join.
My wrapper is as follows:
public IEnumerable<TResultEntity> Join<TResultEntity>(IList<JoinType<BaseEntity, BaseEntity>> joins)
{
var result = new List<TResultEntity>();
if (joins != null && joins.Any())
{
var joinBuilder = new JoinSqlBuilder<T, BaseEntity>();
foreach (var join in joins)
{
joinBuilder = joinBuilder.Join(join.LeftColumn, join.RightColumn, join.LeftSelection, join.RightSelection, join.LeftWhere, join.RightWhere);
}
var connection = this.DataConnection;
using (connection)
{
var joinSql = joinBuilder.SelectDistinct().ToSql();
result = connection.SqlList<TResultEntity>(joinSql);
}
}
return result;
}
Doing the same thing, without the list seems to work:
public IEnumerable<TResultEntity> Join<TLeftTable1, TRightTable1, TLeftTable2, TRightTable2, TResultEntity>(
JoinType<TLeftTable1, TRightTable1> join1,
JoinType<TLeftTable2, TRightTable2> join2)
where TLeftTable1 : BaseEntity
where TRightTable1 : BaseEntity
where TLeftTable2 : BaseEntity
where TRightTable2 : BaseEntity
EDIT - I'm testing using the below call:
// Act
var join1 = new JoinType<AnswerEntity, UserSurveyStateEntity>(
l => l.OwnerId,
r => r.UserId,
x => new { UserId = x.OwnerId, x.QuestionId, AnswerId = x.Id, x.AnswerValue });
var join2 = new JoinType<SurveyEntity, UserSurveyStateEntity>(
l => l.Id,
r => r.SurveyInstanceId,
x => new { SurveyId = x.Id, SurveyName = x.Name, x.StatusValue },
null,
null,
x => x.StatusValue == (int)UserSurveyStatus.Complete);
var joins = new List<JoinType<BaseEntity, BaseEntity>>();
joins.Add(join1.As<JoinType<BaseEntity, BaseEntity>>());
joins.Add(join2.As<JoinType<BaseEntity, BaseEntity>>());
var result = dataAccess.Join<AnswerEntity>(joins).ToList();
EDIT - Now seeing the use case, the error is related to casting to the base type and the builder storing more than one column selector for the concrete BaseEntity. Consider adding an abstract JoinType class, and modifying the JoinType class so it will apply the join for the builder.
For example:
public class Entity
{
public string Id { get; set; }
}
public class Foo
: Entity
{
public string Value { get; set; }
}
public class Bar
: Entity
{
public string FooId { get; set; }
public string Value { get; set; }
}
public abstract class JoinType
{
public abstract JoinSqlBuilder<TNew, TBase> ApplyJoin<TNew, TBase>(
JoinSqlBuilder<TNew, TBase> bldr);
}
public class JoinType<TSource, TTarget>
: JoinType
{
private Expression<Func<TSource, object>> _sourceColumn;
private Expression<Func<TTarget, object>> _destinationColumn;
private Expression<Func<TSource, object>> _sourceTableColumnSelection;
private Expression<Func<TTarget, object>> _destinationTableColumnSelection;
private Expression<Func<TSource, bool>> _sourceWhere;
private Expression<Func<TTarget, bool>> _destinationWhere;
public JoinType(Expression<Func<TSource, object>> sourceColumn,
Expression<Func<TTarget, object>> destinationColumn,
Expression<Func<TSource, object>>
sourceTableColumnSelection = null,
Expression<Func<TTarget, object>>
destinationTableColumnSelection = null,
Expression<Func<TSource, bool>> sourceWhere = null,
Expression<Func<TTarget, bool>> destinationWhere =
null)
{
this._sourceColumn = sourceColumn;
this._destinationColumn = destinationColumn;
this._sourceTableColumnSelection = sourceTableColumnSelection;
this._destinationTableColumnSelection =
destinationTableColumnSelection;
this._sourceWhere = sourceWhere;
this._destinationWhere = destinationWhere;
}
public override JoinSqlBuilder<TNew, TBase> ApplyJoin<TNew, TBase>(
JoinSqlBuilder<TNew, TBase> bldr)
{
bldr.Join(_sourceColumn,
_destinationColumn,
_sourceTableColumnSelection,
_destinationTableColumnSelection,
_sourceWhere,
_destinationWhere);
return bldr;
}
}
public class FooBar
{
[References(typeof(Foo))]
public string FooId { get; set; }
[References(typeof(Bar))]
public string BarId { get; set; }
[References(typeof(Foo))]
public string FooValue { get; set; }
[References(typeof(Bar))]
public string BarValue { get; set; }
}
/*
This join accomplishes the same thing, but just returns the SQL as a string.
*/
public string Join<TResultEntity,TBase>(IList<JoinType>joins)
{
var result = new List<TResultEntity>();
if (joins != null && joins.Any())
{
var joinBuilder = new JoinSqlBuilder<TResultEntity, TBase>();
foreach (var joinType in joins)
{
//call the apply join, and the join type will know the valid types
joinBuilder = joinType.ApplyJoin(joinBuilder);
}
return joinBuilder.SelectDistinct().ToSql();
}
return null;
}
[TestMethod]
public void TestMethod1()
{
OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
var joins = new List<JoinType>();
var jointype1 = new JoinType<Bar, FooBar>(
bar => bar.Id,
bar => bar.BarId,
bar => new { BarId = bar.Id, BarValue = bar.Value }
);
joins.Add(jointype1);
var joinType2 = new JoinType<Foo, FooBar>(
foo => foo.Id,
bar => bar.FooId,
foo => new { FooId = foo.Id, FooValue = foo.Value}
);
joins.Add(joinType2);
var str = Join<FooBar, Bar>(joins);
}
Old Answer - still relevant to the error
This error is caused by your selector join.LeftColumn or your join.RightColumn containing two selectors. Make sure they only contain a single one.
I was able to reproduce the error with the following test:
public class Entity
{
public string Id { get; set; }
}
public class Foo
: Entity
{
public string Value { get; set; }
}
public class Bar
: Entity
{
public string FooId { get; set; }
public string Value { get; set; }
}
public class FooBar
{
[References(typeof(Foo))]
public string FooId { get; set; }
[References(typeof(Bar))]
public string BarId { get; set; }
[References(typeof(Foo))]
public string FooValue { get; set; }
[References(typeof(Bar))]
public string BarValue { get; set; }
}
[TestMethod]
public void TestMethod1()
{
OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
var bldr = new JoinSqlBuilder<FooBar,Bar>();
bldr = bldr.Join<FooBar, Bar>(
bar => bar.BarId,
bar => new { Id1 = bar.Id, Id2 = bar.Id},//<-- this should only contain a single member
bar => new { BarId =bar.BarId },
bar => new { BarId = bar.Id, BarValue = bar.Value},
bar => bar.BarId != null,
bar => bar.Id != null
);
var str = bldr.SelectDistinct().ToSql();
}

automapper, mapping to an interface

I am using automapper (for .net 3.5). Here is an example to illustrate what I am trying to do:
I want to map an A object to a B object. Class definitions:
class A
{
public I1 MyI { get; set; }
}
class B
{
public I2 MyI { get; set; }
}
interface I1
{
string StringProp1 { get; }
}
interface I2
{
string StringProp1 { get; }
}
class CA : I1
{
public string StringProp1
{
get { return "CA String"; }
}
public string StringProp2 { get; set; }
}
class CB : I2
{
public string StringProp1
{
get { return "CB String"; }
}
public string StringProp2 { get; set; }
}
The mapping code:
A a = new A()
{
MyI = new CA()
};
// Mapper.CreateMap ...?
B b = Mapper.Map<A,B>(a);
I want the resulting object b to be populated with an instance of CB. So automapper needs to know that A maps to B, CA maps to CB, and when creating a B populate it's MyI prop with a CB, how do I specify this mapping?
Something like this:
class Program
{
static void Main(string[] args)
{
Mapper.Initialize(x => x.AddProfile<MappingProfile>());
var a = new A()
{
MyI = new CA()
{
StringProp2 = "sp2"
}
};
var b = Mapper.Map<A, B>(a);
Console.WriteLine("a.MyI.StringProp1: " + a.MyI.StringProp1);
Console.WriteLine("b.MyI.StringProp1: " + b.MyI.StringProp1);
}
}
>= AutoMapper 2.0.0
public class MappingProfile : Profile
{
protected override void Configure()
{
CreateMap<CA, CB>();
CreateMap<CA, I2>().As<CB>();
CreateMap<A, B>();
}
}
AutoMapper 1.1.0.188 (.Net 3.5)
public class MappingProfile : Profile
{
protected override void Configure()
{
CreateMap<CA, CB>();
CreateMap<CA, I2>()
.ConstructUsing(Mapper.Map<CA, CB>)
;
CreateMap<A, B>();
}
}

AutoMapper failing to map a simple list

I have used automapper for mapping lists in the past, for for some reason it won't work in this case.
public class MyType1 {
public int Id { get; set; }
public string Description { get; set; }
}
public class MyType2 {
public int Id { get; set; }
public string Description { get; set; }
}
public void DoTheMap() {
Mapper.CreateMap<MyType2, MyType1>();
Mapper.AssertConfigurationIsValid();
var theDto1 = new MyType2() { Id = 1, Description = "desc" };
var theDto2 = new MyType2() { Id = 2, Description = "desc2" };
List<MyType2> type2List = new List<MyType2> { theDto1, theDto2 };
List<MyType1> type1List = Mapper.DynamicMap<List<MyType1>>(type2List);
//FAILURE. NO EXCEPTION, BUT ZERO VALUES
List<MyType1> type1List2 =type2List.Select(Mapper.DynamicMap<MyType1>).ToList();
//SUCCESS, WITH LINQ SELECT
}
Change this:
Mapper.DynamicMap<List<MyType1>>(type2List)
To this:
Mapper.Map<List<MyType1>, List<MyType2>>(type2List);
DynamicMap is only if you don't know the type at compile time - for things like anonymous types.

ValueInjecter question

After working with AutoMapper I came across ValueInjecter on this site. I am trying it out but I am stuck on what is probably a very simple scenario.
But before I dig into the code sample, does anyone know if ValueInjecter works in a Medium-Trust web environment? (Like Godaddy?)
Ok, onto the code! I have the following models:
public class NameComponent
{
public string First { get; set; }
public string Last { get; set; }
public string MiddleInitial { get; set; }
}
public class Person
{
public NameComponent Name { get; set; }
}
that I want to map to the following DTO:
public class PersonDTO : BaseDTO
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set { NotifyPropertyChanged(() => FirstName, ref _firstName, value); }
}
private string _middleInitial;
public string MiddleInitial
{
get { return _middleInitial; }
set { NotifyPropertyChanged(() => MiddleInitial, ref _middleInitial, value); }
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set { NotifyPropertyChanged(() => LastName, ref _lastName, value); }
}
}
So when I want to Map from Model to DTO I need a Model.Name.First -> DTO.FirstName
and when going from DTO to Model I need FirstName -> Name.First. From my understanding this is not a simple Flatten/UnFlatten, because the words also reverse themselves, ie: FirstName <--> Name.First. So First and Last names could use the same kind of rule, but what about MiddleInitial? Model.Name.MiddleInitial -> DTO.MiddleInitial.
I see there are some plugins, but none of them seem to do what I would want. Has anyone else come across this scenario?
the basic idea is that I match the Name with the FirstName, I take this as a pivot point, and in the method that usually sets the value to just one (FirstName) property I set it to 3 properties - that's for the FromNameComp
in the ToNameComp i match the same properties but I take the value from 3 and create one and set it
public class SimpleTest
{
[Test]
public void Testit()
{
var p = new Person { Name = new NameComponent { First = "first", Last = "last", MiddleInitial = "midd" } };
var dto = new PersonDTO();
dto.InjectFrom<FromNameComp>(p);
Assert.AreEqual(p.Name.First, dto.FirstName);
Assert.AreEqual(p.Name.Last, dto.LastName);
Assert.AreEqual(p.Name.MiddleInitial, dto.MiddleInitial);
var pp = new Person();
pp.InjectFrom<ToNameComponent>(dto);
Assert.AreEqual(dto.LastName, pp.Name.Last);
Assert.AreEqual(dto.FirstName, pp.Name.First);
Assert.AreEqual(dto.MiddleInitial, pp.Name.MiddleInitial);
}
public class FromNameComp : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name == "Name" && c.SourceProp.Type == typeof(NameComponent)
&& c.TargetProp.Name == "FirstName"
&& c.SourceProp.Value != null;
}
protected override object SetValue(ConventionInfo c)
{
dynamic d = c.Target.Value;
var nc = (NameComponent)c.SourceProp.Value;
//d.FirstName = nc.First; return nc.First does this
d.LastName = nc.Last;
d.MiddleInitial = nc.MiddleInitial;
return nc.First;
}
}
public class ToNameComponent : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.TargetProp.Name == "Name" && c.TargetProp.Type == typeof(NameComponent)
&& c.SourceProp.Name == "FirstName";
}
protected override object SetValue(ConventionInfo c)
{
dynamic d = c.Source.Value;
var nc = new NameComponent { First = d.FirstName, Last = d.LastName, MiddleInitial = d.MiddleInitial };
return nc;
}
}
public class NameComponent
{
public string First { get; set; }
public string Last { get; set; }
public string MiddleInitial { get; set; }
}
public class Person
{
public NameComponent Name { get; set; }
}
public class PersonDTO
{
public string FirstName { get; set; }
public string MiddleInitial { get; set; }
public string LastName { get; set; }
}
}
But before I dig into the code sample,
does anyone know if ValueInjecter
works in a Medium-Trust web
environment? (Like Godaddy?)
it doesn't use reflection.emit so it should work

Resources