Skip to content

Repository files navigation

data DataFuse v3.0.0

Like GraphQL, but for your heterogeneous backend systems

License: MITMaster-BuildGitHub ReleaseMaster-CodeQL.Net 10.0

DataFuse is a declarative framework that aggregates data from SQL databases, REST APIs, and any heterogeneous datsource into unified, strongly-typed objects — replacing hundreds of lines of manual orchestration code with clean, schema-driven configuration.


The Problem

Building a product page? You need inventory from SQL Server, pricing from a REST API, and reviews from MongoDB. That's 50+ lines of manual fetch-assemble code — sequential, tightly coupled, and repeated across your codebase.

// Without DataFuse: manual orchestration everywherevarproduct=awaitdb.QueryFirstAsync<ProductRecord>("SELECT * FROM Products WHERE Id = @Id",new{Id=productId});varpricing=awaithttpClient.GetFromJsonAsync<PricingResponse>($"https://pricing-api/products/{productId}");varreviews=awaithttpClient.GetFromJsonAsync<ReviewResponse[]>($"https://reviews-api/products/{productId}");product.Price=pricing.Price;product.Reviews=reviews.Select(r =>newReview{Rating=r.Stars,Comment=r.Text}).ToArray();

The Solution

// With DataFuse: declare once, use everywherevarproduct=dataProvider.GetData(newProductRequest{ProductId=42});

DataFuse automatically executes the SQL query first, then runs pricing and reviews API calls in parallel, passes parent results to child queries, and assembles the final typed object.


Quick Start

1. Install

dotnet add package DataFuse.Integration
dotnet add package DataFuse.Adapters.SQL # SQL with Dapper
dotnet add package DataFuse.Adapters.WebAPI # REST APIs
dotnet add package DataFuse.Adapters.MongoDB # MongoDB

2. Define Your Entity

publicclassProduct:IEntity{publicintProductId{get;set;}publicstringName{get;set;}publicdecimalPrice{get;set;}publicdecimalDiscount{get;set;}publicReview[]Reviews{get;set;}}

3. Create Queries

// SQL query — fetches product from databasepublicclassProductQuery:SQLQuery<ProductResult>{protectedoverrideFunc<IDbConnection,Task<ProductResult>>GetQuery(IDataContextcontext,IQueryResultparentQueryResult){varrequest=(ProductRequest)context.Request;return connection =>connection.QueryFirstOrDefaultAsync<ProductResult>("SELECT ProductId as Id, Name, Price FROM Products WHERE ProductId = @Id",new{Id=request.ProductId});}}// MongoDB query — fetches reviews from MongoDB, receives parent resultpublicclassReviewsMongoQuery:MongoQuery<CollectionResult<ReviewResult>>{protectedoverrideFunc<IMongoDatabase,Task<CollectionResult<ReviewResult>>>GetQuery(IDataContextcontext,IQueryResult?parentQueryResult){varproduct=(ProductResult)parentQueryResult;returnasync database =>{varcollection=database.GetCollection<ReviewResult>("reviews");varreviews=awaitcollection.Find(r =>r.ProductId==product.Id).ToListAsync();returnnewCollectionResult<ReviewResult>(reviews);};}}// API query — fetches live pricing from external service, receives parent resultpublicclassPricingApiQuery:WebQuery<PricingResult>{publicPricingApiQuery():base("https://api.pricing.com/"){}protectedoverrideFunc<Uri>GetQuery(IDataContextcontext,IQueryResultparentQueryResult){varproduct=(ProductResult)parentQueryResult;return()=>newUri($"products/{product.Id}/pricing",UriKind.Relative);}}

4. Create Transformers

publicclassProductTransform:BaseTransformer<ProductResult,Product>{publicoverridevoidTransform(ProductResultqueryResult,Productentity){entity.ProductId=queryResult.Id;entity.Name=queryResult.Name;entity.Price=queryResult.Price;}}publicclassPricingTransform:BaseTransformer<PricingResult,Product>{publicoverridevoidTransform(PricingResultqueryResult,Productentity){entity.Price=queryResult.CurrentPrice;entity.Discount=queryResult.DiscountPercent;}}publicclassReviewsTransform:BaseTransformer<CollectionResult<ReviewResult>,Product>{publicoverridevoidTransform(CollectionResult<ReviewResult>queryResult,Productentity){entity.Reviews=queryResult?.Select(r =>newReview{ReviewId=r.Id,Comment=r.Comment,Rating=r.Rating}).ToArray()??Array.Empty<Review>();}}

5. Configure the Schema

publicclassProductConfiguration:EntityConfiguration<Product>{publicoverrideIEnumerable<Mapping<Product,IQueryResult>>GetSchema(){returnCreateSchema.For<Product>().Map<ProductQuery,ProductTransform>(For.Paths("product"),
product =>product.Dependents.Map<PricingApiQuery,PricingTransform>(For.Paths("product/pricing")).Map<ReviewsMongoQuery,ReviewsTransform>(For.Paths("product/reviews"))).End();}}

6. Register & Use

// DI registrationservices.UseDataFuse().WithEngine(c =>newQueryEngine(sqlConfiguration))// SQL.WithEngine<DataFuse.Adapters.WebAPI.QueryEngine>()// REST API.WithEngine(c =>newDataFuse.Adapters.MongoDB.QueryEngine(mongoDatabase))// MongoDB.WithPathMatcher(c =>newXPathMatcher()).WithEntityConfiguration<Product>(c =>newProductConfiguration());services.AddHttpClient();
// Usage — one line to get fully hydrated datapublicclassProductService{privatereadonlyIDataProvider<Product>_dataProvider;publicProductService(IDataProvider<Product>dataProvider)=>_dataProvider=dataProvider;publicProductGetProduct(intproductId)=>_dataProvider.GetData(newProductRequest{ProductId=productId});// Selective loading — only fetch product + reviews, skip other pathspublicProductGetProductWithReviews(intproductId)=>_dataProvider.GetData(newProductRequest{ProductId=productId,SchemaPaths=new[]{"product","product/reviews"}});}

Key Features

FeatureDescription
Declarative SchemaDefine data relationships once with fluent configuration
Automatic ParallelismSibling queries run in parallel — no Task.WhenAll boilerplate
Selective LoadingFetch only the data paths the consumer needs via SchemaPaths
Parent-Child DependenciesParent results flow to child queries automatically
Cross-Source MixingCombine SQL + REST API + MongoDB + EF Core queries in one entity
Type SafetyStrongly-typed queries, results, and transformers
Built-in Caching[CacheResult] attribute for expensive query results
Custom AdaptersAdd any data source by implementing IQueryEngine

Packages

PackagePurposeInstall
DataFuse.IntegrationCore orchestration, DI, helpersdotnet add package DataFuse.Integration
DataFuse.Adapters.SQLSQL via Dapperdotnet add package DataFuse.Adapters.SQL
DataFuse.Adapters.EntityFrameworkEF Coredotnet add package DataFuse.Adapters.EntityFramework
DataFuse.Adapters.WebAPIREST APIs via HttpClientdotnet add package DataFuse.Adapters.WebAPI
DataFuse.Adapters.MongoDBMongoDB via official driverdotnet add package DataFuse.Adapters.MongoDB
DataFuse.Adapters.AbstractionInterfaces & base classesIncluded as dependency

Compatibility

Package.NET.NET Standard.NET Framework
DataFuse.Integration8.0, 9.0, 10.02.1-
DataFuse.Adapters.Abstraction8.0, 9.0, 10.02.1-
DataFuse.Adapters.SQL8.0, 9.0, 10.02.1-
DataFuse.Adapters.WebAPI8.0, 9.0, 10.02.1-
DataFuse.Adapters.MongoDB8.0, 9.0, 10.02.1-
DataFuse.Adapters.EntityFramework10.0--

Documentation

See the Complete Developer Guide for detailed documentation including:

  • Real-world use cases (e-commerce, customer 360, reporting)
  • Core concepts deep dive
  • Query implementation guides (SQL, EF Core, Web API, MongoDB)
  • Transformer patterns
  • Advanced features (caching, selective loading, custom engines)
  • Architecture overview

Support

If you are having problems, please let us know by raising a new issue.

License

This project is licensed with the MIT license.

Version History

The main branch is now on .NET 10.0. Previous versions:

VersionRelease NotesDeveloper Guide
v3.0.0NotesGuide
v2.0.0NotesGuide
v1.0.0NotesGuide

About

DataFuse.Net is a powerful library designed to aggregate data from heterogeneous data stores using a schema-driven approach. It enables developers to hydrate complex object graphs by fetching data from multiple sources (SQL databases, Web APIs, NoSQL stores) using XPath and JSONPath schema mappings.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages