5

Is it possible to use the Entity Framework 6 with the code first pattern and write the models in C# and in IronPython?

The background is, that a few standard models are defined in the c# core, and some custom models has to be defined in IronPython.

EDIT

The custom models were defined in our productive systems for customization. The models should be loaded and added to the DbContext at application startup. Every model is one IronPython file/module and will be loaded from a database (as all other scripts will be).

Not working sample

Program.cs

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IronPython_EF
{
    class Program
    {
        // Private Member
        private static SampleContext context;

        static void Main(string[] args)
        {
            // Setup EntityFramework
            context = new SampleContext();

            // Create IronPython
            var setup = Python.CreateRuntimeSetup(null);
            var runtime = new ScriptRuntime(setup);
            var engine = runtime.GetEngine("IronPython");
            var scriptScope = engine.CreateScope();

            // Set global var
            scriptScope.SetVariable("DBContext", context);

            // Load Model
            ScriptSource modelSource = engine.CreateScriptSourceFromFile("Python\\User.py");
            modelSource.Execute(scriptScope);

            ScriptSource scriptSource = engine.CreateScriptSourceFromFile("Python\\Demo.py");
            scriptSource.Execute(scriptScope);

            // Prevent from exiting
            Console.ReadLine();
        }
    }
}

SampleContext.cs

namespace IronPython_EF
{
    using System;
    using System.Data.Entity;
    using System.Linq;

    public class SampleContext : DbContext
    {


        public SampleContext() : base("name=SampleContext")
        {

        }
    }
}

User.Py

# -----------------------------------------------
# Containing the UserModel
# -----------------------------------------------

# -----------------------------------------------
# Import
from System import Console
# -----------------------------------------------

#
class User(object):

    userId = 0
    userName = ""

    def __init__(self):
        pass

    def get_userId(self):
        return self.userId;

    def set_userId(self, value):
        self.userId = value

    def get_userName(self):
        return self.userName;

    def set_userId(self, value):
        self.userName = value

    UserId = property(get_userId, set_userId)
    UserName = property(get_userName, set_userId)

Demo.py

# -----------------------------------------------
# Demo Python Script, executing something in the
# Sample-DB-Context
# -----------------------------------------------

# -----------------------------------------------
# Import
from System import Console
# -----------------------------------------------

#
Console.WriteLine("Executing demo.py")

# Add User-Model
userSet = DBContext.Set[User]()

# Add User instance
usr = User()
usr.UserName = "Hallo Welt"

userSet.Add(usr)

# Save changes
DBContext.SaveChanges()

I get the exception, that User is not part of the DBContext.

Thank you for your help!

BendEg
  • 20,098
  • 17
  • 57
  • 131
  • 4
    Could add more details on what you are trying to do? You won't be able to just derive DbContext in C# and add your IronPython models as DbSets (which is the typical code first example) as you do not have compiled types you could reference. There could be a way by dynamically creating the model from IronPython types ... How/when would the custom models be defined and where do objects of this type come from in terms of application/architecture? – Simon Opelt Mar 01 '15 at 20:09
  • @SimonOpelt than you for your replay, i added some more details to the question. – BendEg Mar 03 '15 at 08:29
  • The inherent problem with the described approach is the missing type information. How would the python model (assuming it consists of plain python classes and given that function annotations only exist in 3) statically, without exemplary instances containing actual data reflect what entities/properties there are? – Simon Opelt Mar 03 '15 at 22:12
  • @SimonOpelt good question. Tomorrow i will create a sample solution, which demonstrate my problem in code. Hope this will help – BendEg Mar 03 '15 at 22:59
  • Thanks for the samples. If you look at `User.UserName` property how should EF know at `DBContext.Set[User]()` (without having instances with data) what property type to emit? With python 3 one could build on function annotations (e.g. `def get_userName(self) -> str:`) which could communicate to some layer on top of EF that a property of type string would have to be used. – Simon Opelt Mar 05 '15 at 09:56
  • @SimonOpelt thank you for your answer. Would it be possible, to mix *database first* and *code first*? So that the db already exists and we write the models on our own in Python? Than the schem should already exists an known by the EF. – BendEg Mar 05 '15 at 10:03

1 Answers1

0

I'm not sure this is possible as IronPython classes are not .NET classes. It might be possible to write a custom mapper than will generate the classes for you from the IronPython files. But this could get complicated with relationships/indexes/keys etc.

If you HAVE to keep IronPython, and if you are looking for the ORM benefits of EF, then an alternative would be: http://www.sqlalchemy.org/

But if you are looking for the other goodness that EF provides (migrations etc), then it is going to be a bit of a problem.

Tim Norris
  • 256
  • 2
  • 10
  • What do you mean with *IronPython classes are not .Net classes*? Because i can use .Net classes in IronPython and IronPython classis in .Net... Yes, i have to keep IronPython, because it is a very nece DLR-Based language. SqlAlchemy seems not to work with IronPython, because it is made for cPython. – BendEg Mar 03 '15 at 10:45
  • 1
    What I meant was that because it's a dynamic language, it operates in the DLR which sits atop of the CLR. I reckon it would be difficult for the EF plumbing to cope with that but perhaps there are ways. Think of migration files for example: they need to work in a strongly-typed manner so that the database schema is nailed down. I just can't see how this cold work with dynamic languages...but I'm sure someone has tried it and proven me wrong. Good luck in the venture and I hope to see a post back soon showing your solution! – Tim Norris Mar 03 '15 at 12:10