Dapper Extension Get & Update returns errors - dapper

I tried to play with Dapper Extension & MS Access and succeeded up to certain extent. My code is listed below. All the functions works properly (Insert/Count/GetList/Delete) except Get & Update. I have summarised the code below. If anybody wants I can paste all the code here
My Product class
public class Products
{
public string ProductNumber { get; set; }
public string Description { get; set; }
}
And in my main class. I tried to get the product and update it as below. con.Get<Products> function returns an exception with "Sequence contains more than one element" message and con.Update<Products> returns an exception with "At least one Key column must be defined".
using (var con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb"))
{
string ProductNumber = "12";
var product4 = con.Get<Products>(ProductNumber);
product4.ProductNumber = "Baz";
con.Update<Products>(product4);
Console.ReadLine();
}
Even though con.Get<Products> fails con.GetList<Products>(predicate) works perfectly. I did follow this link for setup

If DapperExtensions can't infer a key property called ID from your class, you'll need to explicitly specify one via a class mapper. Assuming the ProductNumber is the primary key in the database, the following example class mapper should set the ProductNumber to be the primary key for DapperExtensions.
using Dapper;
using DapperExtensions;
using DapperExtensions.Mapper;
public class ProductsMapper : ClassMapper<Products>
{
public ProductsMapper()
{
Map(x => x.ProductNumber).Key(KeyType.Assigned);
AutoMap();
}
}
This class can sit somewhere within the same assembly as the rest of your code. Dapper Extensions will automatically pick it up. If you have your classes and Dapper code in separate assemblies, you can point it to your mapper with the following line:
DapperExtensions.DapperExtensions.SetMappingAssemblies({ typeof(ProductsMapper).Assembly })

Related

SSIS Data Flow Task Error: Object reference not set to an instance of an object

I am trying to create a package containing several Data Flow tasks in them. The tasks are fairly similar in nature, but contain fairly important differences.
I have tried to copy the task, then change the things which need changing.
When I run the task by itself it runs fine, however when I run it with all the other tasks in the package I get the below error:
Object reference not set to an instance of an object. at
ScriptMain.Input0_ProcessInputRow(Input0Buffer Row) at
UserComponent.Input0_ProcessInput(Input0Buffer Buffer) at
UserComponent.ProcessInput(Int32 InputID, String InputName,
PipelineBuffer Buffer, OutputNameMap OutputMap) at
Microsoft.SqlServer.Dts.Pipeline.ScriptComponent.ProcessInput(Int32
InputID, PipelineBuffer buffer) at
Microsoft.SqlServer.Dts.Pipeline.ScriptComponentHost.ProcessInput(Int32
inputID, PipelineBuffer buffer)
Not the most friendly error message.
Can anyone tell me what this is and how to fix it? I assume that there is some variable or other attribute which is being repeated, but which one?
Note that many of the columns over the several data flow tasks will have the same column names.
I figured it out in the end. The reason was that the second level objects need to be explicitly declared.
I had
public class Level2
{
public string Somevalue { get; set; }
}
public class RootAttributes
{
public Level2 lvl2 { get; set; }
public string Somevalue2 { get; set; }
}
It should have been
public class Level2
{
public string Somevalue { get; set; }
}
public class RootAttributes
{
public Level2 lvl2 = new Level2;
public string Somevalue2 { get; set; }
}
The weird thing was that the top method worked in several other places.
I had this issue with my send mail task.
As I was using a file connection for my body of the email, I had to create a new file connection and it worked fine.
Use the package run report in vs 2012 to identify in which DFT task package got failed.
Use the view code option of the package to see the whether all the DFT task having proper input.

How to use Dapper's SqlBuilder?

I can't find any documentation or examples I can follow to use the SqlBuilder class.
I need to generate sql queries dynamically and I found this class. Would this be the best option?
the best place to start is to checkout the dapper source code from its github repo and have a look at the SqlBuilder code. The SqlBuilder class is only a 200 lines or so and you should be able to make an informed choice on whether it is right for your needed.
An other option is to build your own. I personally went down this route as it made sense. Dapper maps select querys directly to a class if you name your class properties the same as your database or add an attribute such as displayName to map from you can use reflection to get the property names. Put there names and values into a dictionary and you can genarate sql fairly easy from there.
here is something to get you started:
first an example class that you can pass to your sqlbuilder.
public class Foo
{
public Foo()
{
TableName = "Foo";
}
public string TableName { get; set; }
[DisplayName("name")]
public string Name { get; set; }
[SearchField("fooId")]
public int Id { get; set; }
}
This is fairly basic. Idea behind the DisplayName attribute is you can separate the properties out that you want to include in your auto generation. in this case TableName does not have a DisplayName attribute so will not be picked up by the next class. however you can manually use it when generating your sql to get your table name.
public Dictionary<string, object> GetPropertyDictionary()
{
var propDictionary = new Dictionary<string, object>();
var passedType = this.GetType();
foreach (var propertyInfo in passedType.GetProperties())
{
var isDef = Attribute.IsDefined(propertyInfo, typeof(DisplayNameAttribute));
if (isDef)
{
var value = propertyInfo.GetValue(this, null);
if (value != null)
{
var displayNameAttribute =
(DisplayNameAttribute)
Attribute.GetCustomAttribute(propertyInfo, typeof(DisplayNameAttribute));
var displayName = displayNameAttribute.DisplayName;
propDictionary.Add(displayName, value);
}
}
}
return propDictionary;
}
This method looks at the properties for its class and if they are not null and have a displayname attribute will add them to a dictionary with the displayname value as the string component.
This method is designed to work as part of the model class and would need to be modified to work from a separate helper class. Personally I have it and all my other sql generation methods in a Base class that all my models inherit from.
once you have the values in the dictionary you can use this to dynamically generate sql based on the model you pass in. and you can also use it to populate your dapper DynamicParamaters for use with paramiterized sql.
I hope this helps put you on the right path to solving your problems.

How can I export mongoDB collection into .csv which is readable/compatible in SQL Server

I used mongoexport to export the collection in to csv file along with fields. However when I tried to import the .csv in sql server using SSIS. I got errors and the data in preview section before executing the package was wrong. Can any one please guide me how can I export the data properly which can be easily imported into sql server. I am ready for minor tuning like adding id column or changing data types etc.
So it looks like you are getting a json formatted object for each row in the file. It may be different than that, and if that's the case, how you iterate through each might change a little. But here is something to get you started:
1 - There is no out of the box JSON parser in .NET, but this seems to be a popular utility: http://www.newtonsoft.com/json
2 - If you download the parser above, you'll have to go through a little pain to get it in a useable state with SSIS:
Go to the source folder and open the solution for net40
Sign the assembly
comment out the lines that cause build errors
//[assembly: InternalsVisibleTo("Newtonsoft.Json.Schema")]
//[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests")]
install the assembly to the gac
3 - Once all that is out of the way, add a file connection manager to your package and point it to the mongdb file
4 - Add a dataflow and then add a script component source to the dataflow
5 - In the script component, configure the connection manager that you created in step three, I gave mine the friendly name "MongoDbOutput"
6 - In the Inputs and Outputs section, go to Output0 and add a column for each field in the JSON object, setting datatypes to string as they will be int by default
7 - Open the script and add a reference to Newtonsoft.Json and System.IO
8 - The script below shows how to access the connection string to the file in the connection manager, read the file with a streamreader one line at a time and then parse each JSON object for each address. One line is added for every address and the name and ssn are repeated for each line.
Note also, that I added a person and address class. The json.net is pretty cool, it will take that json and push it into the object - provided all the fields match up. Goog luck!
using System.IO;
using Newtonsoft.Json;
public override void CreateNewOutputRows()
{
object MongoDbPath = Connections.MongoDbOutput.AcquireConnection(null);
string filePath = MongoDbPath.ToString();
using (StreamReader fileContents = new StreamReader(filePath))
{
while (fileContents.Peek() >= 0)
{
var contents = fileContents.ReadLine();
Person person = JsonConvert.DeserializeObject<Person>(contents);
foreach (address address in person.addresses)
{
Output0Buffer.AddRow();
Output0Buffer.name = person.name;
Output0Buffer.ssn = person.ssn;
Output0Buffer.City = address.city;
Output0Buffer.Street = address.street;
Output0Buffer.country = address.cc;
}
}
}
}
public class Person
{
public string name { get; set; }
public string ssn { get; set; }
public address[] addresses
{ get; set; }
}
public class address
{
public string street { get; set; }
public string city { get; set; }
public string cc { get; set; }
}

dreaded "Ids can not be autogenerated for entities with multipart keys"

Ok I’m at a loss, being new to breeze I’m still learning the ropes. My project uses the hot towel template for AngularJs and breeze from John Papa.
He's what I’m trying to achieve: I have a master\slave tables in my database. An "Agency" has many people it can "Notify". Here are the EF classes for the server side:
public class Agency {
public Agency() {
this.Notifies = new HashSet<Notify>();
}
public long Id { get; set; }
[Required, MaxLength(50)]
public string Name { get; set; }
<<removed unneeded details>>
public bool Active { get; set; }
public virtual ICollection<Notify> Notifies { get; set; }
}
public class Notify
{
public long Id { get; set; }
public long? AgencyId { get; set; }
public string Name { get; set; }
<<removed unneeded details>>
public virtual Agency Agency { get; set; }
}
Now the Maps:
public class AgencyMaps : EntityTypeConfiguration<Agency>
{
internal AgencyMaps()
{
HasKey(x => x.Id);
}
}
public class NotifyMap : EntityTypeConfiguration<Notify>
{
internal NotifyMap()
{
HasKey(x => x.Id);
HasOptional(x => x.Agency)
.WithMany(p => p.Notifies)
.HasForeignKey(i => i.AgencyId);
}
}
Now on the client side I use breeze to create new entities like this:
// create a new entity
function create() {
return manager.createEntity(entityName);
}
// create a new notify entity
function createNotify(){
return manager.createEntity(entityNameNotify);
}
Then there are two scenarios I need to achieve:
- First is where I retrieve an existing agency and add additional
people to notify
- Second is where I create a new agency and add people
to notify
Both fail in the same place.
Note: I’m using SQL server and my Id fields are bigint (long) at this point in time.
I’m retrieving the “Agency” entity and placing it in a variable called “vm.agency”. “vm.agency” has a navigation called “notifies” with an entity type of “Notify”. So when I want to create and add a new person I’m calling this function:
function addNotifyRec(){
if (vm.agency !== undefined){
var notifyRec = datacontext.agency.createNotify(); //<<< fails here
notifyRec.agencyId = vm.agency.id;
notifyRec.name = vm.notify.name;
<<removed unneeded details>>
vm.agency.notifies.push(notifyRec);
logSuccess(“New person to notify added”);
}
else
{ logError(“Agency is undefined”); }
}
As soon as the createNotify() is called I get the “Ids can not be autogenerated for entities with multipart keys” error.
So I’m stuck. It seems to me this is a pretty common scenario. I am obviously not understanding the breeze framework well enough to implement this. If you can point me in the right directions I’d appreciate your help.
UPDATE 4/9/2014
I'm thinking i could eliminate this issue altogether if i switch over to guid id and generate them client side. Is this correct thinking?
What's interesting here is that Breeze thinks that Notify.Id and Notify.AgencyId are multi part primary keys but they are actually not. Id is a PK and AgencyId is an FK. The only thing that I can think of is try removing the EntityTypeConfiguration for both Agency and Notify, specifically the part where it specifies HasKey and HasForeignKey. This Fluent API configuration shouldn't be required as EF will match your configuration by convention instead.
I took a different approach on working around my issue. Since i have the luxury to change out the id types, i swapped out the bigint ids to Uuid types and removed the auto generation of the ids in sql. Now i'm just creating my own ids using breeze.core.getUuid() when a new record is created. Not sure this is the most efficient way to work around the issue, but it seems to be working fine.

RIA Services SP2 Function Complex type not visible in Object Context

I am struggling with returning a complex type from my services layer. It doesnt seem to be accessible from my object context.
This is the query in the service layer. All compiling fine.
public IQueryable<USP_GetPostsByThreadID_Result> uspGetPostsByThreadID(int ThreadID)
{
return this.ObjectContext.USP_GetPostsByThreadID(ThreadID).AsQueryable();
}
When I try and call it from my client, the ForumContext is not seeing it. I checked the client generated file and nothing similar is being generated. Help!!!
The name of your method may not meet the expected convention for queries. Try one or both of the following:
Add the [Query] attribute
Rename the method to GetUspPostsByThreadID
Result:
[System.ServiceModel.DomainServices.Server.Query]
public IQueryable<USP_GetPostsByThreadID_Result> GetUspPostsByThreadID(int ThreadID)
{
return this.ObjectContext.USP_GetPostsByThreadID(ThreadID).AsQueryable();
}
Its very common to have a stored procedure returning data from multiple tables. The return type doesn't fit well under any of the Entity Types(Tables). Therefore if we define Complex Type as the return collection of objects from Stored Procedure invocation, it becomes quite a powerful tool for the developer.
Following these steps I have achieved successfully the configuration of complex type on a sample AdventureWorks database.
1. Refer the picture and ensure the Stored procedure and function import is done.
2. Add the Domain Service name it as AdventureDomainService.
3. Now its time to define the tell the RIA services framework to identify my Complex Type as Entity Type. To be able to do this, we need to identify a [Key] DataAnnotation. Entity types provide data structure to the application's data model and by design, each entity type is required to define a unique entity key. We can define key on one property or a set of properties in metadata class file AdventureDomainService.metadata.cs
First define the class then add MetadatatypeAttribute like :
[MetadataTypeAttribute(typeof(CTEmployeeManagers.CTEmployeeManagersMetadata))]
public partial class CTEmployeeManagers
{
internal sealed class CTEmployeeManagersMetadata
{
private CTEmployeeManagersMetadata() { }
[Key]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int ManagerID { get; set; }
public string ManagerFirstName { get; set; }
public string ManagerLastName { get; set; }
}
}
Define the Domain service method to return the collection of objects/entities for populating the Silverlight Grid or any other data consuming controls.
public IQueryable<CTEmployeeManagers> GetEmployeeManagers(int empId)
{
return this.ObjectContext.GetEmployeeManagers(empId).AsQueryable();
}
We define IQueryable if we are to fetch the records from datasources like SQL, whereas we define IEnumerable if we are to fetch the records from in memory collections,dictionaty,arrays.lists, etc.
Compile the server side to generate the client proxy.
In the Silverlight side open the MainPage.xaml or wherever the datagrid is put, then add following namespaces :
using System.ServiceModel.DomainServices.Client;
using SLBusinessApplication.Web;
using SLBusinessApplication.Web.Services;
..
Load the data and display:
public partial class MyPage : Page
{
AdventureDomainContext ctx = new AdventureDomainContext();
public MyPage()
{
InitializeComponent();
LoadOperation loadOp = this.ctx.Load(this.ctx.GetEmployeeManagersQuery(29));
myGrid.ItemsSource = loadOp.Entities;
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
That is all that is needed to do.
It has to be part of an entity. Complex types cannot be returned by themselves

Resources